|
发表于 2020-6-11 00:17:17
|
查看: 5911 |
回复: 1
环境搭建 使用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,选择Debuger->Run->Remote Linux Debugger
使用IDA远程调试linux虚拟机中的网络编程客户端
点击ok就可以进行远程调试了。
反汇编分析 首先我们需要找到main函数(前面的是数据初始化过程,不是写的函数的部分)
使用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:stdin@@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虚拟机中的网络编程客户端
3、继续执行,得到结果:服务器接收到的内容更变为11111而并非输入的123
使用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.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【 投诉建议】板块发帖举报。
|