查看: 255|回复: 1

[转载图文] 使用IDA远程调试linux虚拟机中的网络编程客户端

[复制链接]
发表于 2020-6-11 00:17:17 | 显示全部楼层 |阅读模式
环境搭建  使用windows下面的ida pro 6.6调试Linux下面的程序需要使用ida的远程调试功能。
首先将ida文件夹中的dbgsrv/linux_serverx64文件放入需要调试程序的同级文件夹中。再使用chmod a+x linux_serverx64 改变该文件的权限。
  运行linux_serverx64

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

  打开IDA,选择Debuger->Run->Remote Linux Debugger

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

  点击ok就可以进行远程调试了。
反汇编分析  首先我们需要找到main函数(前面的是数据初始化过程,不是写的函数的部分)

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

  然后进入的就是client程序反编译出来的汇编代码
[pre].text:00000000004008C6                 push    rbp
.text:00000000004008C7                 mov     rbp, rsp
.text:00000000004008CA                 sub     rsp, 840h  //提升堆栈
.text:00000000004008D1                 mov     rax, fs:28h
.text:00000000004008DA                 mov     [rbp+var_8], rax
.text:00000000004008DE                 xor     eax, eax
.text:00000000004008E0                 mov     rax, 2E302E302E373231h
.text:00000000004008EA                 mov     [rbp+var_820], rax   //[rbp+var_820]为2E302E302E373231h
.text:00000000004008F1                 mov     [rbp+var_818], 31h   //[rbp+var_818]即为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     [rbp+var_838], eax   //局部变量[rbp+var_838]就是sockfd
.text:0000000000400914                 lea     rax, [rbp+var_830]
.text:000000000040091B                 mov     edx, 10h      //sizeof(struct sockaddr_in)
.text:0000000000400920                 mov     esi, 0        //0
.text:0000000000400925                 mov     rdi, rax    //rax = [rbp+var_830] 即一个局部变量 struct sockaddr_in servaddr
.text:0000000000400928                 call    sub_400740  //调用memset(&servaddr,0,sizeof(servaddr))函数
.text:000000000040092D                 mov     [rbp+var_830], 2
.text:0000000000400936                 mov     edi, 1F40h   //0x1f40 = 8000 可见端口为8000
.text:000000000040093B                 call    sub_400710   //调用htons
.text:0000000000400940                 mov     [rbp+var_82E], ax  //将转换后的端口号保存到[rbp+var_82E]
.text:0000000000400947                 lea     rax, [rbp+var_830]  //rax = [rbp+var_830] 即一个局部变量 struct sockaddr_in servaddr
.text:000000000040094E                 lea     rdx, [rax+4]
.text:0000000000400952                 lea     rax, [rbp+var_820]  //[rbp+var_820]为2E302E302E373231h
.text:0000000000400959                 mov     rsi, rax      //rsi为[rbp+var_820]为2E302E302E373231h
.text:000000000040095C                 mov     edi, 2     //AF_INET
.text:0000000000400961                 call    sub_400780    //调用inet_pton
.text:0000000000400966                 lea     rcx, [rbp+var_830]
.text:000000000040096D                 mov     eax, [rbp+var_838]    //局部变量[rbp+var_838]就是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:[email protected]@GLIBC_2_2_5  //fget()的第三个参数stdin
.text:0000000000400993                 lea     rax, [rbp+var_810]   
.text:000000000040099A                 mov     esi, 400h  //字符串长度
.text:000000000040099F                 mov     rdi, rax
.text:00000000004009A2                 call    sub_400770   //调用 fgets()函数
.text:00000000004009A7                 lea     rax, [rbp+var_810]
.text:00000000004009AE                 mov     rdi, rax  //将内容设为参数给strlen()
.text:00000000004009B1                 call    sub_400700   //调用 strlen函数
.text:00000000004009B6                 mov     rdx, rax    //发送的信息的长度
.text:00000000004009B9                 lea     rsi, [rbp+var_810]   //发送的信息
.text:00000000004009C0                 mov     eax, [rbp+var_838]   //sockfd
.text:00000000004009C6                 mov     ecx, 0   
.text:00000000004009CB                 mov     edi, eax
.text:00000000004009CD                 call    sub_400720   //调用send()函数
.text:00000000004009D2                 lea     rsi, [rbp+var_410]
.text:00000000004009D9                 mov     eax, [rbp+var_838]   //将连接套接字赋给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     [rbp+var_834], eax  //将recv接收到的内容保存给[rbp+var_834]
.text:00000000004009F6                 mov     eax, [rbp+var_834]
.text:00000000004009FC                 cdqe              //转换DWORD(eax)成QWORD(rax)
.text:00000000004009FE                 mov     [rbp+rax+var_410], 0
.text:0000000000400A06                 lea     rax, [rbp+var_410]   //此时的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, [rbp+var_838]   //将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 [rax+rax+00000000h]
.text:0000000000400A36 main            endp ; sp-analysis failed[/pre]  验证猜想--更改发送内容
1、首先定位到buf地址,由上述反汇编分析中可知,eax中的值为buf的地址。即通过fgets获得的输入内容的存储地址。
2、单步调试,再输入内容后,通过ida的hex-view更改具体值

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

  3、继续执行,得到结果:服务器接收到的内容更变为11111而并非输入的123

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

使用IDA远程调试linux虚拟机中的网络编程客户端

  4、修改接收到的消息
源程序代码分析[pre]#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[MAXLINE];  
char    buf[MAXLINE];  
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[rec_len]= '\0';  
printf("Received:%s\n",buf);  //打印接收到的消息
close(sockfd);    //关闭套接字
exit(0);  
}
[/pre]
游客,如果您要查看本帖隐藏内容请回复




温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

0

主题

56

帖子

0

精华

中级会员

Rank: 8Rank: 8

学币
94
荣耀
0
rank
0
违规
0

    发表于 2020-6-11 10:22:29 | 显示全部楼层
    看了LZ的帖子,我只想说一句很好很强大!
    学逆向论坛-免费的逆向学习论坛
    微信公众号
    快速回复 返回顶部 返回列表