690827027 发表于 2010-9-30 18:43

怎样逆向MFC程序

最近抽空逆向一个MFC程序,顺便把自己的一些方法写上,供大家参考,方法可能不怎么好,里面可能有一些

错误,请大家多指教

(1)

方法一

寻找程序初始化函数

通常导入表里面会存在

AfxOleInit (COM初始化)

AfxEnableControlContainer(Ole初始化)

AfxGetModuleState(获取模块状态)

CoInitialize(COM初始化 API)

GdiplusStartup (GDI+初始化)

SetUnhandledExceptionFilter(截获异常处理)

Enable3dControls();            

在这些函数里面下段就可以断在其中

方法二

uf MFC80U!AfxWinMain
MFC80U!AfxWinMain :
   21 7831d25f 53            push    ebx
   21 7831d260 56            push    esi
   21 7831d261 57            push    edi
   24 7831d262 83cbff          or      ebx,0FFFFFFFFh
   25 7831d265 e8ca2cffff      call    MFC80U!AfxGetModuleThreadState (7830ff34)
   25 7831d26a 8b7004          mov   esi,dword ptr
   26 7831d26d e84f2cffff      call    MFC80U!AfxGetModuleState (7830fec1)
   29 7831d272 ff74241c      push    dword ptr
   29 7831d276 8b7804          mov   edi,dword ptr
   29 7831d279 ff74241c      push    dword ptr
   29 7831d27d ff74241c      push    dword ptr
   29 7831d281 ff74241c      push    dword ptr
   29 7831d285 e8f3ca0200      call    MFC80U!AfxWinInit (78349d7d)
   29 7831d28a 85c0            test    eax,eax
   29 7831d28c 743c            je      MFC80U!AfxWinMain+0x6b (7831d2ca)

MFC80U!AfxWinMain+0x2f :
   33 7831d28e 85ff            test    edi,edi
   33 7831d290 740e            je      MFC80U!AfxWinMain+0x41 (7831d2a0)

MFC80U!AfxWinMain+0x33 :
   33 7831d292 8b07            mov   eax,dword ptr
   33 7831d294 8bcf            mov   ecx,edi
   33 7831d296 ff9098000000    call    dword ptr
   33 7831d29c 85c0            test    eax,eax
   33 7831d29e 742a            je      MFC80U!AfxWinMain+0x6b (7831d2ca)

MFC80U!AfxWinMain+0x41 :
   37 7831d2a0 8b06            mov   eax,dword ptr
   37 7831d2a2 8bce            mov   ecx,esi
   37 7831d2a4 ff5058          call    dword ptr
   37 7831d2a7 85c0            test    eax,eax
   37 7831d2a9 7516            jne   MFC80U!AfxWinMain+0x62 (7831d2c1)

MFC80U!AfxWinMain+0x4c :
   39 7831d2ab 394620          cmp   dword ptr ,eax
   39 7831d2ae 7408            je      MFC80U!AfxWinMain+0x59 (7831d2b8)

MFC80U!AfxWinMain+0x51 :
   42 7831d2b0 8b4e20          mov   ecx,dword ptr
   42 7831d2b3 8b01            mov   eax,dword ptr
   42 7831d2b5 ff5068          call    dword ptr

MFC80U!AfxWinMain+0x59 :
   44 7831d2b8 8b06            mov   eax,dword ptr
   44 7831d2ba 8bce            mov   ecx,esi
   44 7831d2bc ff5070          call    dword ptr
   49 7831d2bf eb07            jmp   MFC80U!AfxWinMain+0x69 (7831d2c8)

MFC80U!AfxWinMain+0x62 :
   47 7831d2c1 8b06            mov   eax,dword ptr
   47 7831d2c3 8bce            mov   ecx,esi
   47 7831d2c5 ff505c          call    dword ptr

MFC80U!AfxWinMain+0x69 :
   47 7831d2c8 8bd8            mov   ebx,eax

MFC80U!AfxWinMain+0x6b :
   61 7831d2ca e887cd0200      call    MFC80U!AfxWinTerm (7834a056)
   61 7831d2cf 5f            pop   edi
   61 7831d2d0 5e            pop   esi
   62 7831d2d1 8bc3            mov   eax,ebx
   62 7831d2d3 5b            pop   ebx
   63 7831d2d4 c21000          ret   10h


此处即为MFC程序初始化点

MFC 应用程序类派生于CWinApp InitInstance 这个函数

为虚函数,也为程序初始化点 eax为虚函数表起址


37 7831d2a4 ff5058          call    dword ptr

方法三

下段MFC80U!CWinApp::CWinApp

贴上此函数源代码

    if (lpszAppName != NULL)
      m_pszAppName = _tcsdup(lpszAppName);
    else
      m_pszAppName = NULL;

    // initialize CWinThread state
    AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
    AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
    ASSERT(AfxGetThread() == NULL);
    pThreadState->m_pCurrentWinThread = this;
    ASSERT(AfxGetThread() == this);
    m_hThread = ::GetCurrentThread();
    m_nThreadID = ::GetCurrentThreadId();

    // initialize CWinApp state
    ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
    pModuleState->m_pCurrentWinApp = this;
    ASSERT(AfxGetApp() == this);

    // in non-running state until WinMain
    m_hInstance = NULL;
    m_pszHelpFilePath = NULL;
    m_pszProfileName = NULL;
    m_pszRegistryKey = NULL;
    m_pszExeName = NULL;
    m_pRecentFileList = NULL;
    m_pDocManager = NULL;
    m_atomApp = m_atomSystemTopic = NULL;
    m_lpCmdLine = NULL;
    m_pCmdInfo = NULL;

    // initialize wait cursor state
    m_nWaitCursorCount = 0;
    m_hcurWaitCursorRestore = NULL;

    // initialize current printer state
    m_hDevMode = NULL;
    m_hDevNames = NULL;
    m_nNumPreviewPages = 0;   // not specified (defaults to 1)

    // initialize DAO state
    m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called

    // other initialization
    m_bHelpMode = FALSE;
    m_nSafetyPoolSize = 512;      // default size


等此函数返回之后再返回上一层函数,(此函数返回时候里面置的只是CWinApp虚函数表首地址)在[+58h]

处下段即可 还有

    m_hThread = ::GetCurrentThread();
    m_nThreadID = ::GetCurrentThreadId();

这两个函数也可以下段

方法四

.text:0056973D               push    offset unk_6337D8
.text:00569742               push    offset unk_633474
.text:00569747               call    _initterm

下段此函数 _initterm 但是里面全局类构造函数太多,可能有误下

此函数源码

#ifdef CRTDLL
void __cdecl _initterm (
#else/* CRTDLL */
static void __cdecl _initterm (
#endif/* CRTDLL */
      _PVFV * pfbegin,
      _PVFV * pfend
      )
{
      /*
         * walk the table of function pointers from the bottom up, until
         * the end is encountered.Do not skip the first entry.The initial
         * value of pfbegin points to the first valid entry.Do not try to
         * execute what pfend points to.Only entries before pfend are valid.
         */
      while ( pfbegin < pfend )
      {
            /*
             * if current table entry is non-NULL, call thru it.
             */
            if ( *pfbegin != NULL )
                (**pfbegin)();
            ++pfbegin;
      }
}

2 关于MFC消息的跟踪

现在以跟踪对话框消息 WM_INITDIALOG

bp uSER32!DispatchClientMessage "j(poi(esp+8)=110) 'kv' ;'g'"

ChildEBP RetAddrArgs to Child            
0012fb88 77d28eec 006ed3d8 00000110 0020066e USER32!DispatchClientMessage (FPO: )
0012fbb0 7c92e453 0012fbc0 00000018 006ed3d8 USER32!__fnDWORD+0x24 (FPO: )
0012fbd4 77d194be 77d2c174 0020066e 00000110 ntdll!KiUserCallbackDispatcher+0x13 (FPO: )
0012fc10 77d2651a 006ed3d8 00000110 0020066e USER32!NtUserMessageCall+0xc
0012fcc8 77d2683e 00400000 006ed3d8 00000040 USER32!InternalCreateDialog+0x9df (FPO: )
0012fcec 77d39b43 00400000 00418860 00000000 USER32!CreateDialogIndirectParamAorW+0x33 (FPO: )
0012fd0c 5f4363e7 00400000 00418860 00000000 USER32!CreateDialogIndirectParamA+0x1b (FPO: )
0012fdb0 5f436a22 00418860 00000000 00400000 MFC42D!CWnd::CreateDlgIndirect+0x296 (CONV: thiscall)
*** WARNING: Unable to verify checksum for GetSomeAlo.exe
0012fe18 0040142c 00000000 00000000 7ffde000 MFC42D!CDialog::DoModal+0x144 (CONV: thiscall)
0012fee8 5f4359f3 00000000 00000000 7ffde000 GetSomeAlo!*****+0x6c
0012ff08 00402628 00400000 00000000 00141f17 MFC42D!AfxWinMain+0x83 (CONV: stdcall)
0012ff20 00402533 00400000 00000000 00141f17 GetSomeAlo!WinMain+0x18
0012ffc0 7c817067 00000000 00000000 7ffde000 GetSomeAlo!WinMainCRTStartup+0x1b3
0012fff0 00000000 00402380 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: )
eax=0012fbc0 ebx=004188a0 ecx=0012fbb0 edx=00000002 esi=006ed3d8 edi=00000110
eip=77d28e53 esp=0012fb8c ebp=0012fbb0 iopl=0         nv up ei pl zr na pe nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000             efl=00000246
USER32!DispatchClientMessage:
77d28e53 6a10            push    10h

段下之后就是这样的

然后第一个进入EXE就是一定是消息处理函数

Hmily 发表于 2010-9-30 18:47

顶谭牛....教大家怎么找关键函数!学习!

65302666 发表于 2010-9-30 18:54

学习楼主了。。。

五爷 发表于 2010-9-30 18:54

mobai谭

z26650 发表于 2010-9-30 19:26

继续膜拜。。
但是好像都是动态编译的?。静态不知道有没有特征:lol

bookding 发表于 2010-9-30 19:42

mfc的确是心中的痛啊……

xiakexing 发表于 2010-10-2 08:06

这个我也不会,向楼主学习

wxhwhmanshan 发表于 2011-1-2 13:45

我也不会,向楼主学习

Kiζs~乄 发表于 2011-2-26 18:31

看不懂啊

ap1018 发表于 2011-2-28 16:06

膜拜下。破解 一直 2溜子!
页: [1]
查看完整版本: 怎样逆向MFC程序