zoukankan      html  css  js  c++  java
  • 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);
    printf(“My pid is: %d. ”, getpid());
    while(1){
    sleep(3); /* sleep for 3 secs */
    }
    printf(“I break out ”);
    return 0;
    }
    说明:
    此题只需上交实现文档、源码。源码中请以注释注明平台、系统。比如32位linux 3.2。
    将上述代码编译好(不能修改),运行,想办法令其跳出循环,打印出”I break out ”。
    你的代码不能调用任何其他软件,比如od之类。
    如果你知道内核栈、pt_regs结构体、函数栈桢,那么你很有可能成功。
    成功打印出”I break out ”但同时引发段错误得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!
    ");
    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
    ");
    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!
    ");
    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 ,根据这个就可以写入数据了。

  • 相关阅读:
    SQL SERVER事务处理
    设计模式之简单工厂模式(静态工厂方法)
    设计模式之工厂方法模式
    为什么静态成员变量要通过类外初始化赋值?
    c++中可以对类中私有成员中的静态变量初始化吗?
    C++中的虚函数(virtual function)
    C++ 基础学习笔记(2)函数(测试题)
    c++中子对象的初始化可在复合类的构造函数的函数体内进行吗?还是子对象的初始化只能在初始化列表中进行?
    C++学习笔记(五)虚函数表解析(转)
    看过的书籍(转)
  • 原文地址:https://www.cnblogs.com/Joy7/p/3391959.html
Copyright © 2011-2022 走看看