XDCTF 2013 code2 跳出死循环

题目:编写一个程序(比如kernel module),使附件2.c中的程序跳出死循环。2.c中的代码如下:
#include 
int main(int argc, char *argv[])
{
int n = 1;
printf(“Address of n :%x\n”,&n);
printf(“My pid is: %d.\n”, getpid());
while(1){
sleep(3); /* sleep for 3 secs */
}
printf(“I break out\n”);
return 0;
}
说明:
此题只需上交实现文档、源码。源码中请以注释注明平台、系统。比如32位linux 3.2。
将上述代码编译好(不能修改),运行,想办法令其跳出循环,打印出”I break out\n”。
你的代码不能调用任何其他软件,比如od之类。
如果你知道内核栈、pt_regs结构体、函数栈桢,那么你很有可能成功。
成功打印出”I break out\n”但同时引发段错误得2/3分。

 

屌丝不会linux,所以只能windows

 

思路:debug编译出上面代码可以看到while(1)的反汇编代码为mov ecx,1,只需用WriteProcessMemory将1修改为0即可跳出死循环

 

反汇编:

 1 0040D470 >  55              push ebp
 2 0040D471    8BEC            mov ebp,esp
 3 0040D473    83EC 44         sub esp,44
 4 0040D476    53              push ebx
 5 0040D477    56              push esi
 6 0040D478    57              push edi
 7 0040D479    8D7D BC         lea edi,dword ptr ss:[ebp-44]
 8 0040D47C    B9 11000000     mov ecx,11
 9 0040D481    B8 CCCCCCCC     mov eax,CCCCCCCC
10 0040D486    F3:AB           rep stos dword ptr es:[edi]
11 0040D488    C745 FC 0100000>mov dword ptr ss:[ebp-4],1
12 0040D48F    8D45 FC         lea eax,dword ptr ss:[ebp-4]
13 0040D492    50              push eax
14 0040D493    68 942F4200     push xd_code2.00422F94                   ; ASCII "Address of n :%x
15 "
16 0040D498    E8 83020000     call xd_code2.printf
17 0040D49D    83C4 08         add esp,8
18 0040D4A0    E8 4B000000     call xd_code2._getpid
19 0040D4A5    50              push eax
20 0040D4A6    68 842F4200     push xd_code2.00422F84                   ; ASCII "My pid is: %d.
21 "
22 0040D4AB    E8 70020000     call xd_code2.printf
23 0040D4B0    83C4 08         add esp,8
24 0040D4B3    B9 01000000     mov ecx,1                                ; while(1)
25 0040D4B8    85C9            test ecx,ecx
26 0040D4BA    74 13           je short xd_code2.0040D4CF
27 0040D4BC    8BF4            mov esi,esp
28 0040D4BE    6A 03           push 3
29 0040D4C0    FF15 18A24200   call dword ptr ds:[<&KERNEL32.Sleep>]    ; kernel32.Sleep
30 0040D4C6    3BF4            cmp esi,esp
31 0040D4C8    E8 C33BFFFF     call xd_code2.00401090
32 0040D4CD  ^ EB E4           jmp short xd_code2.0040D4B3
33 0040D4CF    68 1C204200     push xd_code2.0042201C                   ; ASCII "I break out
34 "
35 0040D4D4    E8 47020000     call xd_code2.printf
36 0040D4D9    83C4 04         add esp,4
37 0040D4DC    33C0            xor eax,eax
38 0040D4DE    5F              pop edi
39 0040D4DF    5E              pop esi
40 0040D4E0    5B              pop ebx
41 0040D4E1    83C4 44         add esp,44
42 0040D4E4    3BEC            cmp ebp,esp
43 0040D4E6    E8 A53BFFFF     call xd_code2.00401090
44 0040D4EB    8BE5            mov esp,ebp
45 0040D4ED    5D              pop ebp
46 0040D4EE    C3              retn

 

代码:

 1 #include "stdafx.h"
 2 #include <windows.h>
 3 #include <TlHelp32.h>
 4 #define PID 2200 //每次运行手动修改
 5 BYTE* GetBase(int Pid);
 6 
 7 int _tmain(int argc, _TCHAR* argv[])
 8 {
 9     BYTE *base = GetBase(PID);
10 
11     //printf_s("%x", base);
12     HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
13     byte NewCode = 0;
14 
15     //测试发现地址不会变,都为0x40D4B4,故GetBase函数都不需要
16     if (WriteProcessMemory(hProcess, base + 0xD4B4, &NewCode, 1, NULL))
17     {
18         printf_s("Write Success!\n");
19     }
20     
21     getchar();
22     return 0;
23 }
24 
25 BYTE* GetBase(int Pid)
26 {
27     BYTE *result = NULL;
28     HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Pid);
29     if (hSnap == INVALID_HANDLE_VALUE)
30     {
31         printf_s("CreateToolhelp32Snapshot failed\n");
32     }
33 
34     MODULEENTRY32 Me32;
35     Me32.dwSize = sizeof(MODULEENTRY32);
36 
37     BOOL bRet = Module32First(hSnap, &Me32);
38     while(bRet)
39     {
40         if (Me32.th32ProcessID == Pid)
41         {
42             printf_s("Have Found!\n");
43             result = Me32.modBaseAddr;    //返回主模块的基地址
44             break;
45         }
46         bRet = Module32Next(hSnap, &Me32);
47     }
48 
49     CloseHandle(hSnap);
50     return result;
51 }

 

运行效果:

 

跳出成功

 

总结:

while(1)在debug编译下为mov ecx,1  test ecx, ecx, jz XXXXXXXX ,根据这个就可以写入数据了。

posted @ 2013-10-28 10:39  JoyChou  阅读(421)  评论(0编辑  收藏  举报