roger 发表于 2020-6-11 00:17:17

使用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 *****


Augus 发表于 2020-6-11 10:22:29

看了LZ的帖子,我只想说一句很好很强大!
页: [1]
查看完整版本: 使用IDA远程调试linux虚拟机中的网络编程客户端