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 ,根据这个就可以写入数据了。