使用IDA远程调试linux虚拟机中的网络编程客户端
环境搭建 使用windows下面的ida pro 6.6调试Linux下面的程序需要使用ida的远程调试功能。首先将ida文件夹中的dbgsrv/linux_serverx64文件放入需要调试程序的同级文件夹中。再使用chmod a+x linux_serverx64 改变该文件的权限。
运行linux_serverx64
打开IDA,选择Debuger->Run->Remote Linux Debugger
点击ok就可以进行远程调试了。
反汇编分析 首先我们需要找到main函数(前面的是数据初始化过程,不是写的函数的部分)
然后进入的就是client程序反编译出来的汇编代码
.text:00000000004008C6 push rbp
.text:00000000004008C7 mov rbp, rsp
.text:00000000004008CA sub rsp, 840h//提升堆栈
.text:00000000004008D1 mov rax, fs:28h
.text:00000000004008DA mov , rax
.text:00000000004008DE xor eax, eax
.text:00000000004008E0 mov rax, 2E302E302E373231h
.text:00000000004008EA mov , rax //为2E302E302E373231h
.text:00000000004008F1 mov , 31h //即为31h
.text:00000000004008FA mov edx, 0 //0
.text:00000000004008FF mov esi, 1//SOCK_STREAM
.text:0000000000400904 mov edi, 2//AF_INET
.text:0000000000400909 call sub_4007B0//调用socket(AF_INET,SOCK_STREAM,0)函数
.text:000000000040090E mov , eax //局部变量就是sockfd
.text:0000000000400914 lea rax,
.text:000000000040091B mov edx, 10h //sizeof(struct sockaddr_in)
.text:0000000000400920 mov esi, 0 //0
.text:0000000000400925 mov rdi, rax //rax = 即一个局部变量 struct sockaddr_in servaddr
.text:0000000000400928 call sub_400740//调用memset(&servaddr,0,sizeof(servaddr))函数
.text:000000000040092D mov , 2
.text:0000000000400936 mov edi, 1F40h //0x1f40 = 8000 可见端口为8000
.text:000000000040093B call sub_400710 //调用htons
.text:0000000000400940 mov , ax//将转换后的端口号保存到
.text:0000000000400947 lea rax, //rax = 即一个局部变量 struct sockaddr_in servaddr
.text:000000000040094E lea rdx,
.text:0000000000400952 lea rax, //为2E302E302E373231h
.text:0000000000400959 mov rsi, rax //rsi为为2E302E302E373231h
.text:000000000040095C mov edi, 2 //AF_INET
.text:0000000000400961 call sub_400780 //调用inet_pton
.text:0000000000400966 lea rcx,
.text:000000000040096D mov eax, //局部变量就是sockfd
.text:0000000000400973 mov edx, 10h //第三个参数大小
.text:0000000000400978 mov rsi, rcx //第二个参数
.text:000000000040097B mov edi, eax //第一个参数
.text:000000000040097D call sub_4007A0 //调用connect函数
.text:0000000000400982 mov edi, offset aSendMsgToServe ; "send msg to server: "
.text:0000000000400987 call sub_4006F0 //调用 printf函数
.text:000000000040098C mov rdx, cs:stdin@@GLIBC_2_2_5//fget()的第三个参数stdin
.text:0000000000400993 lea rax,
.text:000000000040099A mov esi, 400h//字符串长度
.text:000000000040099F mov rdi, rax
.text:00000000004009A2 call sub_400770 //调用 fgets()函数
.text:00000000004009A7 lea rax,
.text:00000000004009AE mov rdi, rax//将内容设为参数给strlen()
.text:00000000004009B1 call sub_400700 //调用 strlen函数
.text:00000000004009B6 mov rdx, rax //发送的信息的长度
.text:00000000004009B9 lea rsi, //发送的信息
.text:00000000004009C0 mov eax, //sockfd
.text:00000000004009C6 mov ecx, 0
.text:00000000004009CB mov edi, eax
.text:00000000004009CD call sub_400720 //调用send()函数
.text:00000000004009D2 lea rsi,
.text:00000000004009D9 mov eax, //将连接套接字赋给eax
.text:00000000004009DF mov ecx, 0 //recv 最后一个参数
.text:00000000004009E4 mov edx, 400h //接受大小
.text:00000000004009E9 mov edi, eax //socket连接套接字
.text:00000000004009EB call sub_4006E0 //调用recv函数
.text:00000000004009F0 mov , eax//将recv接收到的内容保存给
.text:00000000004009F6 mov eax,
.text:00000000004009FC cdqe //转换DWORD(eax)成QWORD(rax)
.text:00000000004009FE mov , 0
.text:0000000000400A06 lea rax, //此时的rax即为recv()函数接收到的东西
.text:0000000000400A0D mov rsi, rax
.text:0000000000400A10 mov edi, offset aReceivedS ; "Received:%s\n" //将这个字符串的地址给edi给后面打印函数传参
.text:0000000000400A15 mov eax, 0
.text:0000000000400A1A call sub_400730//调用printf()函数
.text:0000000000400A1F mov eax, //将sockfd赋给eax
.text:0000000000400A25 mov edi, eax //将sockfd赋给edi
.text:0000000000400A27 call sub_400750 //调用close(sockfd)
.text:0000000000400A2C mov edi, 0
.text:0000000000400A31 call sub_400790 //exit(0)
.text:0000000000400A36 db 2Eh
.text:0000000000400A36 nop word ptr
.text:0000000000400A36 main endp ; sp-analysis failed 验证猜想--更改发送内容
1、首先定位到buf地址,由上述反汇编分析中可知,eax中的值为buf的地址。即通过fgets获得的输入内容的存储地址。
2、单步调试,再输入内容后,通过ida的hex-view更改具体值
3、继续执行,得到结果:服务器接收到的内容更变为11111而并非输入的123
4、修改接收到的消息
源程序代码分析#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<arpa/inet.h> //设置头文件
#define MAXLINE 1024 //定义最大发送大小
#define PORT 8000 //定义端口号
int main()
{
int sockfd, n, rec_len;
char sendline;
char buf;
struct sockaddr_in servaddr;
char ipstr[] = "127.0.0.1";/ /变量定义
sockfd = socket(AF_INET, SOCK_STREAM, 0);//调用套接字函数
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
inet_pton(AF_INET, ipstr, &servaddr.sin_addr.s_addr);
connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));//连接服务器
printf("send msg to server: \n");
fgets(sendlig, MAXLINE, stdin);//录入消息
send(sockfd, sendline, strlen(sendline), 0) ; //发送消息
rec_len = recv(sockfd, buf, MAXLINE,0);//接受消息
buf= '\0';
printf("Received:%s\n",buf);//打印接收到的消息
close(sockfd); //关闭套接字
exit(0);
}
**** Hidden Message *****
看了LZ的帖子,我只想说一句很好很强大!
页:
[1]