The Code Project ¡¡
All Topics, MFC / C++ >> Threads, Processes & IPC >> Processes

Three Ways to Inject Your Code into Another Process
By Robert Kuster

´Ù¸¥ ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£¿¡ Äڵ带 ÁÖÀÔÇÑ ÈÄ ±× ÇÁ·Î¼¼½ºÀÇ ÄÁÅØ½ºÆ® ³»¿¡¼­ ÀÌ Äڵ带 ½ÇÇàÇÏ´Â ¹æ¹ý. 
¡¡
    ¿ªÀÚ : jang_tech@null2root.org
    Last  : 2005. 08. 08
  • ÀÌ ¹®¼­´Â ¿ªÀÚ Ç¥±â¸¦ ºü¶ß¸®Áö ¾ÊÀº ÇÑ ´©±¸³ª ¸¶À½´ë·Î ¹èÆ÷Çϼŵµ µË´Ï´Ù.
  • ¹®¼­ ³¡ÀÇ Áú/´ä ºÎºÐÀº ¹ø¿ªÇÏÁö ¾Ê¾ÒÀ¸¸ç ¿À¿ªµµ ÀÖÀ» ¼ö ÀÖ½À´Ï´Ù.
  • ÀÌ ¹®¼­·Î ÀÎÇØ ¹ß»ýÇÏ´Â ¾î¶°ÇÑ ¹®Á¦µµ ¿ªÀڴ åÀÓÁú ¼ö ¾ø´Ù´Â °ÍÀ» ¹àÈü´Ï´Ù.
¡¡
¡¡ ¡¡

¸ñÂ÷

¼Ò°³

 WinSpy

ÄÚµåÇÁ·ÎÁ§Æ®¿¡´Â ÀÌ¹Ì ¸î °³ÀÇ ÆÐ½º¿öµå ½ºÆÄÀÌ Æ©Å͸®¾óÀÌ ¿Ã¶ó¿Í ÀÖÁö¸¸ À̵éÀº ¸ðµÎ À©µµ¿ìÁî ÈÅ¿¡ ÀÇÁ¸Çϰí ÀÖ´Ù. ÀÌ·± À¯Æ¿¸®Æ¼¸¦ ¸¸µå´Â ´Ù¸¥ ¹æ¹ýÀº ¾øÀ»±î? ¹æ¹ýÀÌ ÀÖ´Ù. ÇÏÁö¸¸ ÀÌ ÆäÀÌÁö¿¡¼­ ¸ðµç ³»¿ëµéÀ» ¸íÈ®È÷ Çϱâ À§ÇØ ¸ÕÀú ¹®Á¦Á¡µéÀ» ¸®ºä ÇØº¸±â·Î ÇÑ´Ù.

¿ì¸®ÀÇ ÀÀ¿ëÇÁ·Î±×·¥¿¡ ¼ÓÇ졂 ¾È ¼ÓÇ졂 ¾î¶² ÄÁÆ®·ÑÀÇ ³»¿ëµéÀ» "Àбâ" À§Çؼ­ ÀϹÝÀûÀ¸·Î ÀÌ ÄÁÆ®·Ñ¿¡ WM_GETTEXT ¸Þ½ÃÁö¸¦ Àü¼ÛÇÑ´Ù. À̰ÍÀº ÇϳªÀÇ Æ¯º°ÇÑ case¸¦ Á¦¿ÜÇÑ´Ù¸é ¿¡µðÆ® ÄÁÆ®·Ñ¿¡µµ Àû¿ëÇÒ ¼ö ÀÖ´Ù. ¿¡µðÆ® ÄÁÆ®·ÑÀÌ ´Ù¸¥ ÇÁ·Î¼¼½º¿¡ ¼ÓÇϰí ES_PASSWORD ½ºÅ¸ÀÏÀÌ ¼³Á¤µÇ¾î ÀÖ´Ù¸é ÀÌ·¯ÇÑ Á¢±Ù¹ýÀº ½ÇÆÐÇÑ´Ù. ÆÐ½º¿öµå ÄÁÆ®·ÑÀ» "¼ÒÀ¯ÇÏ´Â" ÇÁ·Î¼¼½º¸¸ÀÌ WM_GETTEXT¸¦ °æÀ¯ÇÏ¿© ±× ³»¿ëÀ» ¾òÀ» ¼ö ÀÖ´Ù. ±×·¯¹Ç·Î ¿ì¸®ÀÇ ¹®Á¦Á¡Àº ¾Æ·¡¿Í °°Àº Á¡À¸·Î ¾ÐÃàµÈ´Ù. Áï ¾î¶»°Ô Çϸé

::SendMessage( hPwdEdit, WM_GETTEXT, nMaxChars, psBuffer );

¸¦ ´Ù¸¥ ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£ ³»¿¡¼­ ½ÇÇà½Ãų ¼ö Àִ°¡ ÇÏ´Â Á¡À¸·Î ¾ÐÃàµÈ´Ù.

ÀϹÝÀûÀ¸·Î ÀÌ ¹®Á¦¸¦ Ǫ´Â ¹æ¹ý¿¡´Â 3°¡ÁöÀÇ °¡´É¼ºÀÌ ÀÖ´Ù.

  1. ¿ì¸®ÀÇ Äڵ带 DLL¿¡ ³ÖÀº ÈÄ ÀÌ DLLÀ» windows hooks¸¦ ÀÌ¿ëÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡ map ÇÑ´Ù.
  2. ¿ì¸®ÀÇ Äڵ带 DLL¿¡ ³Ö°í ÀÌ DLLÀ» CreateRemoteThread¿Í LoadLibrary Å×Å©´ÐÀ» ÀÌ¿ëÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡ map ÇÑ´Ù.
  3. µ¶¸³ÀûÀÎ DLLÀ» ÀÛ¼ºÇÏ´Â ´ë½Å WriteProcessMemory¸¦ °æÀ¯ÇÏ¿© ¿ì¸®ÀÇ Äڵ带 ¿ø°Ý ÇÁ·Î¼¼½º¿¡ Á÷Á¢ º¹»çÇÑ ÈÄ CreateRemoteThread¸¦ ÀÌ¿ëÇÏ¿© À̰ÍÀ» ½ÇÇàÇÑ´Ù. ÀÌ Å×Å©´Ð¿¡ °üÇÑ ÀÚ¼¼ÇÑ ¼³¸íÀº ¿©±â¿¡¼­ ¹ß°ßÇÒ ¼ö ÀÖ´Ù.

I. À©µµ¿ìÁî ÈÅ

µ¥¸ð ÀÀ¿ëÇÁ·Î±×·¥ : HookSpy ¿Í HookInjEx

À©µµ¿ìÁî ÈÅÀÇ ±âº»ÀûÀÎ ¿ªÇÒÀº ¸î¸î ¾²·¹µåÀÇ ¸Þ½ÃÁö Æ®·¡ÇÈÀ» ¸ð´ÏÅÍ ÇÏ´Â °ÍÀÌ´Ù. ÀϹÝÀûÀ¸·Î ¾Æ·¡¿Í °°Àº °ÍÀÌ ÀÖ´Ù.

  1. ·ÎÄà ÈÅ :  À̰ÍÀ¸·Î´Â ¿ì¸®ÀÇ ÇÁ·Î¼¼½º¿¡ ¼ÓÇÏ´Â ¸ðµç ¾²·¹µåÀÇ ¸Þ½ÃÁö Æ®·¡ÇÈÀ» ¸ð´ÏÅÍ ÇÑ´Ù.
  2. ¸®¸ðÆ® ÈÅ : ¾Æ·¡ Áß Çϳª°¡ µÉ ¼ö ÀÖ´Ù.
    1. thread-specific : ´Ù¸¥ ÇÁ·Î¼¼½º¿¡ ¼ÓÇÏ´Â ¾²·¹µåÀÇ ¸Þ½ÃÁö Æ®·¡ÇÈÀ» ¸ð´ÏÅÍ Çϱâ À§ÇØ.
    2. system-wide : ½Ã½ºÅÛ¿¡¼­ ÇöÀç ½ÇÇàµÇ°í ÀÖ´Â ¸ðµç ¾²·¹µåµéÀÇ ¸Þ½ÃÁö Æ®·¡ÇÈÀ» ¸ð´ÏÅÍ Çϱâ À§ÇØ.

ÈÅÀÌ µÉ ¾²·¹µå°¡ ´Ù¸¥ ÇÁ·Î¼¼½º¿¡ ¼ÓÇÑ´Ù¸é(À§ÀÇ case 2a¿Í 2b) ¿ì¸®ÀÇ ÈÅ ÇÁ·Î½ÃÀú´Â µ¿Àû ¸µÅ© ¶óÀ̺귯¸®(DLL)¿¡ Á¸ÀçÇØ¾ß ÇÑ´Ù. ±×·¯¸é ½Ã½ºÅÛÀÌ ÈÅ ÇÁ·Î½ÃÀú¸¦ Æ÷ÇÔÇÏ´Â DLLÀ» ÈÅÀÌ µÇ´Â ¾²·¹µåÀÇ ÁÖ¼Ò °ø°£À¸·Î map ÇÑ´Ù. À©µµ¿ìÁî´Â ÈÅ ÇÁ·Î½ÃÀú¸¸ÀÌ ¾Æ´Ï¶ó Àüü DLLÀ» map ÇÑ´Ù. À©µµ¿ìÁî ÈÅÀÌ ´Ù¸¥ ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£¿¡ Äڵ带 ÁÖÀÔÇϱâ À§ÇØ ÀÌ¿ëµÉ ¼ö ÀÖ´Â ÀÌÀ¯µµ ÀÌ ¶§¹®ÀÌ´Ù.

ÀÌ ¹®¼­¿¡¼­ ÇÊÀÚ´Â ´õ ÀÌ»ó ÈÅ¿¡ ´ëÇØ ¾ð±ÞÇÏ°í ½ÍÁö ¾ÊÁö¸¸(ÀÚ¼¼ÇÑ °ÍÀº MSDN¿¡¼­ SetWindowHookEx API¸¦ ÂüÁ¶Çϱ⠹ٶ÷) ´Ù¸¥ ¹®¼­¿¡¼­ ¹ß°ßÇϱâ ÈûµéÁö¸¸ ¸Å¿ì À¯¿ëÇÑ 2°³ÀÇ ÈùÆ®¸¦ Á¦°øÇØÁÖ°Ú´Ù.

  1. SetWindowsHookEx¿¡ ´ëÇÑ ¼º°øÀûÀΠȣÃâ ÈÄ ½Ã½ºÅÛÀº DLLÀ» ÈÅÀÌ µÈ ¾²·¹µåÀÇ ÁÖ¼Ò °ø°£À¸·Î ÀÚµ¿À¸·Î map ÇÏÁö¸¸ ¹Ýµå½Ã ¹Ù·Î map ÇÏ´Â °ÍÀº ¾Æ´Ï´Ù. À©µµ¿ìÁî ÈÅÀº ¸ðµÎ ¸Þ½ÃÁö¿Í °ü·ÃµÇ¹Ç·Î DLLÀº ÀûÀýÇÑ À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§±îÁö´Â »ç½Ç »ó map µÇÁö ¾Ê´Â´Ù. ¿¹¸¦ µé¸é

    ¿©·¯ºÐÀÌ Æ¯Á¤ ¾²·¹µåÀÇ ¸ðµç nonqueued ¸Þ½ÃÁöµé(WH_CALLWNDPROC)À» ¸ð´ÏÅÍ ÇÏ´Â ÈÅÀ» ¼³Ä¡Çß´Ù¸é ¸Þ½ÃÁö°¡ (ƯÁ¤ À©µµ¿ìÀÇ) ÈÅÀÌ µÇ´Â ¾²·¹µå¿¡ ½ÇÁ¦·Î Àü¼ÛµÉ ¶§±îÁö ÀÌ DLLÀº ¿ø°Ý ÇÁ·Î¼¼½º¿¡ map µÇÁö ¾ÊÀ» °ÍÀÌ´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ ¸Þ½ÃÁö°¡ ÈÅÀÌ µÉ ¾²·¹µå¿¡ Àü¼ÛµÇ±â Àü¿¡ UnhookWindowsHookEx°¡ È£ÃâµÈ´Ù¸é DLLÀº °áÄÚ ¿ø°Ý ÇÁ·Î¼¼½º¿¡ map µÇÁö ¾ÊÀ» °ÍÀÌ´Ù(SetWindowsHookEx¿¡ ´ëÇÑ È£Ãâ ÀÚü°¡ ¼º°øÇßÀ»Áö¶óµµ). ¹Ù·Î mappingÀÌ µÇµµ·Ï ÇÏ·Á¸é SetWindowsHookEx¿¡ ´ëÇÑ È£Ãâ Á÷ÈÄ¿¡ °ü·ÃµÈ ¾²·¹µå¿¡ ÀûÀýÇÑ À̺¥Æ®¸¦ Àü¼ÛÇÑ´Ù.

    UnhookWindowsHookEx È£Ãâ ÈÄÀÇ DLLÀÇ unmapping¿¡ ´ëÇÑ °Íµµ µ¿ÀÏÇÏ´Ù. ÀûÀýÇÑ À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§±îÁö DLLÀº »ç½Ç »ó unmap µÇÁö ¾Ê´Â´Ù.

  2. ÈÅÀ» ¼³Ä¡ÇÒ ¶§ À̵éÀº ½Ã½ºÅÛ ÀüüÀÇ performance¿¡ ¿µÇâÀ» ¹ÌÄ¥ ¼ö ÀÖ´Ù(ƯÈ÷ system-wide ÈÅÀÇ °æ¿ì). ÇÏÁö¸¸ ÀÌ·± ´ÜÁ¡Àº ¸Þ½ÃÁö trap ÀåÄ¡·Î¼­°¡ ¾Æ´Ï¶ó DLL mapping ¸ÞÄ¿´ÏÁò ¸ñÀûÀ¸·Î¸¸ thread-specific ÈÅÀ» ÀÌ¿ëÇÑ´Ù¸é ½±°Ô ±Øº¹ÇÒ ¼ö ÀÖ´Ù. ¾Æ·¡ÀÇ ÄÚµå Á¶°¢À» Âü°íÇ϶ó.
    BOOL APIENTRY DllMain( HANDLE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved )
    {
        if( ul_reason_for_call == DLL_PROCESS_ATTACH )
        {
            // Increase reference count via LoadLibrary
            char lib_name[MAX_PATH]; 
            ::GetModuleFileName( hModule, lib_name, MAX_PATH );
            ::LoadLibrary( lib_name );
    
            // Safely remove hook
            ::UnhookWindowsHookEx( g_hHook );
        }    
        return TRUE;
    }
    

    ±×·±µ¥ ¹«½¼ ÀÏÀÌ ÀϾÀ»±î? ¸ÕÀú ¿ì¸®´Â À©µµ¿ìÁî ÈÅÀ» °æÀ¯ÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ´ëÇØ DLLÀ» map Çß´Ù. ±×·± ÈÄ ÀÌ DLLÀÌ ½ÇÁ¦·Î mapÀÌ µÈ Á÷ÈÄ¿¡ ¿ì¸®´Â À̰ÍÀ» ´Ù½Ã unhook ÇÑ´Ù. Á¤»óÀûÀ¸·Î´Â ÈÅÀÌ µÈ ¾²·¹µå¿¡ ù ¹øÂ° ¸Þ½ÃÁö°¡ µµ´ÞÇÏ´Â ¼ø°£ ÀÌ DLLµµ ¿ª½Ã unmap µÉ °ÍÀÌ´Ù. Æ®¸¯À¸·Î¼­ ¿ì¸®´Â LoadLibrary¸¦ ÅëÇØ DLLÀÇ ÂüÁ¶ Ä«¿îÆ®¸¦ Áõ°¡½ÃÅ´À¸·Î½á ÀÌ ummappingÀ» ¹æÁöÇÑ´Ù.

    ³²Àº Àǹ®Á¡Àº ÇÒ ÀÏÀ» ´Ù ¸¶Ä£ ÈÄ ÀÌ DLLÀ» ¾î¶»°Ô unload Çϴ°¡ ÇÏ´Â Á¡ÀÌ´Ù. ¿ì¸®´Â ÀÌ¹Ì ¾²·¹µå¸¦ unhook ÇßÀ¸¹Ç·Î UnhookWindowsHookEx´Â ÀÌ·± ÀÛ¾÷À» ÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù. ÀÌ ¹®Á¦´Â ¾Æ·¡¿Í °°ÀÌ ÇÔÀ¸·Î½á ÇØ°áÇÒ ¼ö ÀÖ´Ù.

    • DLLÀ» unmap ÇÏ·Á°í Çϱâ Á÷Àü¿¡ ´Ù¸¥ ÈÅÀ» ¼³Ä¡ÇÑ´Ù.
    • ¿ø°Ý ¾²·¹µå¿¡ ´ëÇØ "Ư¼ö" ¸Þ½ÃÁö¸¦ Àü¼ÛÇÑ´Ù.
    • ¿©·¯ºÐÀÇ ÈÅ ÇÁ·Î½ÃÀú¿¡¼­ ÀÌ ¸Þ½ÃÁö¸¦ catch ÇÑ´Ù. À̰Ϳ¡ ¹ÝÀÀÇØ¼­  FreeLibrary¿Í UnhookWindowsHookEx¸¦ È£ÃâÇÑ´Ù.

    ÀÌÁ¦ ÈÅÀº ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ´ëÇØ¼­ ¶Ç´Â ¿ø°Ý ÇÁ·Î¼¼½º·ÎºÎÅÍ mapping/unmappingÀ» ÇÏ´Â µ¿¾È¿¡¸¸ ÀÌ¿ëµÇ¹Ç·Î "ÈÅÀÌ µÇ´Â" ¾²·¹µåÀÇ performance¿¡ À¯ÀǹÌÇÑ ¿µÇâÀ» ¹ÌÄ¡Áö ¾Ê´Â´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ ¾Æ·¡¿¡¼­ ¾ð±ÞÇÒ LoadLibrary Å×Å©´Ð(Section II ÂüÁ¶)º¸´Ù ´ë»ó ÇÁ·Î¼¼½º¸¦ ´ú °£¼·ÇÏ´Â DLL mapping ¸ÞÄ¿´ÏÁòÀ» ¾Ë¾Æ º¸¾Ò´Ù. ±×·¸Áö¸¸ ÀÌ ÇØ°áÃ¥Àº LoadLibrary Å×Å©´Ð¿¡ ¹ÝÇØ À©NT¿Í À©9x¿¡ ´ëÇØ ¸ðµÎ µ¿ÀÛÇÑ´Ù.

    ±×·±µ¥ ¾ðÁ¦ ÀÌ Æ®¸¯À» ÀÌ¿ëÇØ¾ß ÇÒ±î? Ç×»ó DLLÀÌ ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ ¿À·£ ±â°£ Á¸ÀçÇϰí(Áï ´Ù¸¥ ÇÁ·Î¼¼½º¿¡ ¼ÓÇÏ´Â ÄÁÆ®·ÑÀ» subclass ÇÒ °æ¿ì) ´ë»ó ÇÁ·Î¼¼½º¸¦ ÃÖ¼ÒÇÑ °£¼·ÇÏ°í ½ÍÀ» ¶§ ÀÌ¿ëÇØ¾ß ÇÑ´Ù. HookSpy¿¡¼­´Â DLLÀÌ Àá½Ã µ¿¾È(ÆÐ½º¿öµå¸¦ ¾Ë¾Æ³»±â¿¡ ÃæºÐÇÒ Á¤µµÀÇ) ÁÖÀԵDZ⠶§¹®¿¡ ÀÌ Æ®¸¯À» ÀÌ¿ëÇÏÁö ¾Ê¾Ò´Ù. ÀÌ Æ®¸¯À» º¸¿©ÁÖ±â À§ÇØ ÇÊÀÚ´Â HookInjEx¶ó´Â ´Ù¸¥ ¿¹Á¦¸¦ ¸¸µé¾ú´Ù. HookInjEx´Â DLLÀ» "explorer.exe"·Î map/unmap Çϴµ¥ ¿©±â¿¡¼­ À̰ÍÀº ½ÃÀÛ ¹öưÀ» subclass ÇÑ´Ù. Áï À̰ÍÀº ½ÃÀÛ ¹öưÀÇ ¿ÞÂÊ ¸¶¿ì½º Ŭ¸¯°ú ¿À¸¥ÂÊ ¸¶¿ì½º Ŭ¸¯À» Àüȯ(swap)ÇÑ´Ù.

HookSpy¿Í HookInjEx¿Í À̵éÀÇ ¼Ò½º´Â ÀÌ ¹®¼­ÀÇ Ã¹ ¸Ó¸®¿¡ ÀÖ´Â ´Ù¿î·Îµå ÆÐŰÁö¿¡¼­ ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù.

II. CreateRemoteThread¿Í LoadLibrary Å×Å©´Ð

µ¥¸ð ÀÀ¿ëÇÁ·Î±×·¥ : LibSpy

ÀϹÝÀûÀ¸·Î ¸ðµç ÇÁ·Î¼¼½º´Â LoadLibrary API¸¦ ÀÌ¿ëÇÏ¿© DLLÀ» µ¿ÀûÀ¸·Î ·Îµå ÇÒ ¼ö ÀÖ´Ù. ÇÏÁö¸¸ ¾î¶»°Ô ÇØ¾ß ¿ÜºÎÀÇ ÇÁ·Î¼¼½º°¡ ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÒ ¼ö ÀÖ°Ô ÇÒ ¼ö ÀÖÀ»±î? ÇØ´äÀº CreateRemoteThread¸¦ ÀÌ¿ëÇÏ´Â °ÍÀÌ´Ù.

¸ÕÀú LoadLibrary¿Í FreeLibrary APIÀÇ ÇÔ¼ö ¼±¾ðÀ» »ìÆìº¸ÀÚ.

HINSTANCE LoadLibrary(
  LPCTSTR lpLibFileName   // ¶óÀ̺귯¸® ¸ðµâÀÇ ÆÄÀÏ ¸íÀÇ ÁÖ¼Ò
);

BOOL FreeLibrary(
  HMODULE hLibModule      // ·Îµå µÈ ¶óÀ̺귯¸® ¸ðµâ¿¡ ´ëÇÑ ÇÚµé
);

ÀÌÁ¦ À̵éÀ» CreateRemoteThread¿¡ Àü´ÞµÇ´Â ¾²·¹µå ·çƾÀÎ ThreadProcÀÇ ÇÔ¼ö ¼±¾ð°ú ºñ±³Çغ¸ÀÚ.

DWORD WINAPI ThreadProc(
  LPVOID lpParameter   // ¾²·¹µå µ¥ÀÌÅÍ
);

À§¿¡¼­ º¼ ¼ö ÀÖµíÀÌ ¸ðµç ÇÔ¼öµéÀÌ µ¿ÀÏÇÑ È£Ãâ °ü·Ê¸¦ ÀÌ¿ëÇÏ¸ç ¸ðµÎ 32ºñÆ® ÀÎÀÚ¸¦ ¹Þ¾ÆµéÀδÙ. ¶ÇÇÑ ¹ÝȯµÇ´Â °ªÀÇ Å©±â°¡ µ¿ÀÏÇÏ´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ ¿ì¸®´Â CreateRemoteThread¿¡ ´ëÇÑ ¾²·¹µå ·çƾÀ¸·Î¼­ LoadLibrary/FreeLibrary¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ Àü´ÞÇÒ ¼öµµ ÀÖ´Ù.

ÇÏÁö¸¸ ¿©±â¿¡´Â µÎ °¡ÁöÀÇ ¹®Á¦°¡ ÀÖ´Ù(¾Æ·¡ÀÇ CreateRemoteThread¿¡ ´ëÇÑ ¼³¸í ÂüÁ¶).

  1. CreateRemoteThreadÀÇ lpStartAddress ÀÎÀÚ´Â ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ÀÇ ¾²·¹µå ·çƾÀÇ ½ÃÀÛ ÁÖ¼Ò¸¦ ³ªÅ¸³»¾ß ÇÑ´Ù.
  2. ThreadFunc¿¡ Àü´ÞµÇ´Â ÀÎÀÚÀÎ lpParameter°¡ ÀϹÝÀûÀÎ 32ºñÆ® °ªÀ¸·Î ÇØ¼®µÈ´Ù¸é(FreeLibrary´Â À̰ÍÀ» HMODULE·Î ÇØ¼®ÇÔ) ¸ðµç °ÍÀº Àß µ¹¾Æ°£´Ù. ÇÏÁö¸¸ lpParameter°¡ Æ÷ÀÎÅÍ·Î ÇØ¼®µÈ´Ù¸é(LoadLibraryA´Â À̰ÍÀ» char ½ºÆ®¸µ¿¡ ´ëÇÑ Æ÷ÀÎÅÍ·Î ÇØ¼®ÇÔ) À̰ÍÀº ¿ø°Ý ÇÁ·Î¼¼½ºÀÇ Æ¯Á¤ µ¥ÀÌÅ͸¦ °¡¸®ÄÑ¾ß ÇÑ´Ù.

ù ¹øÂ° ¹®Á¦´Â »ç½Ç ÀÚüÀûÀ¸·Î ÇØ°áµÈ´Ù. LoadLibrary¿Í FreeLibray´Â µÑ ´Ù  kernel32.dll¿¡ Á¸ÀçÇÏ´Â ÇÔ¼öµéÀÌ´Ù. kernel32´Â ¸ðµç "Á¤»ó" ÇÁ·Î¼¼½º¿¡¼­ Ç×»ó Á¸ÀçÇÏ¸ç µ¿ÀÏÇÑ ·Îµå ÁÖ¼Ò¿¡ ÀÖ´Â °ÍÀÌ º¸ÁõµÇ¹Ç·Î(ºÎ·Ï A ÂüÁ¶) LoadLibrary/FreeLibrayÀÇ ÁÖ¼Ò´Â ¸ðµç ÇÁ·Î¼¼½º¿¡¼­ ¿ª½Ã µ¿ÀÏÇÏ´Ù. À̰ÍÀº ¿ø°Ý ÇÁ·Î¼¼½º¿¡ À¯È¿ÇÑ Æ÷ÀÎÅͰ¡ Àü´ÞµÇ´Â °ÍÀ» º¸ÁõÇØÁØ´Ù.

µÎ ¹øÂ° ¹®Á¦ ¶ÇÇÑ ½±°Ô ÇØ°áµÈ´Ù. Áï ´Ü¼øÇÏ°Ô WriteProcessMemory¸¦ ÅëÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡ DLL ¸ðµâ À̸§(LoadLibrary¿¡ ÇÊ¿äÇÑ)À» º¹»çÇØÁØ´Ù.

±×·¡¼­ CreateRemoteThread ¿Í LoadLibrary Å×Å©´ÐÀ» ÀÌ¿ëÇÏ·Á¸é ¾Æ·¡¿Í °°Àº ´Ü°è¸¦ µû¸¥´Ù.

  1. ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ´ëÇÑ HANDLEÀ» ¾ò´Â´Ù(OpenProcess).
  2. ¿ø°Ý ÇÁ·Î¼¼½º ³»¿¡¼­ DLL À̸§À» À§ÇÑ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù(VirtualAllocEx).
  3. ÇÒ´çµÈ ¸Þ¸ð¸®¿¡ Àüü °æ·Î¸¦ Æ÷ÇÔÇÏ´Â DLL À̸§À» ±â·ÏÇÑ´Ù(WriteProcessMemory).
  4. CreateRemoteThread¿Í LoadLibrary¸¦ ÀÌ¿ëÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ¿©·¯ºÐÀÇ DLLÀ» map ÇÑ´Ù.
  5. ¿ø°Ý ¾²·¹µå°¡ Á¾·áÇÒ ¶§±îÁö ±â´Ù¸°´Ù(WaitForSingleObject). À̰ÍÀº LoadLibrary¿¡ ´ëÇÑ È£ÃâÀÌ ¹ÝȯÇÒ ¶§±îÁö ±â´Ù¸®´Â °ÍÀÌ´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ ÀÌ ¾²·¹µå´Â ¿ì¸®ÀÇ DllMain(DLL_PROCESS_ATTACH¶ó´Â reasonÀ¸·Î È£ÃâµÊ)ÀÌ ¹ÝȯÇÏ´Â ¼ø°£ Á¾·áÇÒ °ÍÀÌ´Ù.
  6. ¿ø°Ý ¾²·¹µåÀÇ Å»Ãâ Äڵ带 ¾ò´Â´Ù(GetExitCodeThread). ÀÌ °ªÀº LoadLibrary¿¡ ÀÇÇØ ¹ÝȯµÇ´Â °ªÀ¸·Î¼­ ¿ì¸®ÀÇ map µÈ DLLÀÇ base address(HMODULE)¶ó´Â Á¡¿¡ ÁÖÀÇÇ϶ó.
  7. ´Ü°è 2¿¡¼­ ÇÒ´çµÈ ¸Þ¸ð¸®¸¦ ÇØÁ¦ÇÑ´Ù(VirtualFreeEx).
  8. CreateRemoteThread¿Í FreeLibrary¸¦ ÀÌ¿ëÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ DLLÀ» unload ÇÑ´Ù. FreeLibrary¿¡ ´Ü°è 6¿¡¼­ ¹ÝȯµÈ HMODULEÀ» Àü´ÞÇÑ´Ù(CreateRemoteThreadÀÇ lpParameter ¸¦ °æÀ¯ÇÏ¿©).
    ÁÖÀÇ : ¿©·¯ºÐÀÇ ÁÖÀÔµÈ DLLÀÌ »õ·Î¿î ¾²·¹µå¸¦ spawn Çß´Ù¸é ÀÌ DLLÀ» unloading Çϱâ Àü¿¡ ±×µéÀÌ Á¾·áµÇ¾ú´ÂÁö¸¦ È®ÀÎÇ϶ó.
  9. ¾²·¹µå°¡ Á¾·áÇÒ ¶§±îÁö ±â´Ù¸°´Ù(WaitForSingleObject).

¶ÇÇÑ ÀÛ¾÷ÀÌ ³¡³µ´Ù¸é ¸ðµç ÇÚµéµéÀ» ´Ý´Â °ÍÀ» ÀØÁö ¸»±â ¹Ù¶õ´Ù. Áï ´Ü°è 4¿Í 8¿¡¼­ »ý¼ºµÈ µÎ °³ÀÇ ¾²·¹µå¿¡ ´ëÇÑ ÇÚµé°ú ´Ü°è 1¿¡¼­ ¹ÝȯµÈ ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ÇÚµéÀ» ´Ý´Â´Ù.

ÀÌÁ¦ ½ÇÁ¦·Î À§ÀÇ ´Ü°èµéÀÌ ¾î¶² ½ÄÀ¸·Î ±¸ÇöµÇ¾ú´ÂÁö¸¦ »ìÆìº¸±â À§ÇØ LibSpyÀÇ ¼Ò½º ÀϺθ¦ °ËÅäÇØº¸ÀÚ. °£´ÜÈ÷ Çϱâ À§ÇØ ¿¡·¯ ó¸®¿Í À¯´ÏÄÚµå Áö¿øÀÌ Á¦°ÅµÇ¾ú´Ù.

HANDLE hThread;
char    szLibPath[_MAX_PATH];  // "LibSpy.dll" ¸ðµâÀÇ À̸§
                               // (Àüü °æ·Î¸¦ Æ÷ÇÔ!);
void*   pLibRemote;   // szLibPath°¡ º¹»çµÉ  
                      // ÁÖ¼Ò(¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ÀÇ)
DWORD   hLibModule;   // ·Îµå µÈ ¸ðµâÀÇ base address(==HMODULE);
HMODULE hKernel32 = ::GetModuleHandle("Kernel32");

// szLibPath ÃʱâÈ­
//...

// 1. szLibPath¸¦ À§ÇØ ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù
// 2. ÇÒ´çµÈ ¸Þ¸ð¸®¿¡ szLibPath¸¦ ±â·ÏÇÑ´Ù
pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath),
                               MEM_COMMIT, PAGE_READWRITE );
::WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath,
                      sizeof(szLibPath), NULL );


// ¿ø°Ý ÇÁ·Î¼¼½º·Î "LibSpy.dll"À» ·ÎµåÇÑ´Ù
// (CreateRemoteThread¿Í LoadLibrary¸¦ ÀÌ¿ëÇÏ¿©)
hThread = ::CreateRemoteThread( hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE) ::GetProcAddress( hKernel32,
                                       "LoadLibraryA" ),
             pLibRemote, 0, NULL );
::WaitForSingleObject( hThread, INFINITE );

// ·Îµå µÈ ¸ðµâÀÇ ÇÚµéÀ» ¾ò´Â´Ù
::GetExitCodeThread( hThread, &hLibModule );

// Clean up
::CloseHandle( hThread );
::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE );

¿ì¸®ÀÇ SendMessage(½ÇÁ¦·Î ¿ì¸®°¡ ÁÖÀÔÇÏ°í ½Í¾îÇÏ´Â ÄÚµå)°¡ DllMain(DLL_PROCESS_ATTACH)¿¡ À§Ä¡Çϰí ÀÖ´Ù°í °¡Á¤ÇÑ´Ù¸é À̰ÍÀº ÀÌÁ¦ ÀÌ¹Ì ½ÇÇàµÇ¾úÀ» °ÍÀÌ´Ù. ±×·¯¹Ç·Î ÀÌÁ¦ ´ë»ó ÇÁ·Î¼¼½º¿¡¼­ DLLÀ» unload ÇÒ ½ÃÁ¡ÀÌ´Ù.

// ´ë»ó ÇÁ·Î¼¼½º¿¡¼­ "LibSpy.dll"À» unload ÇÑ´Ù
// (CreateRemoteThread¿Í FreeLibrary¸¦ ÀÌ¿ëÇÏ¿©)
hThread = ::CreateRemoteThread( hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE) ::GetProcAddress( hKernel32,
                                       "FreeLibrary" ),
            (void*)hLibModule, 0, NULL );
::WaitForSingleObject( hThread, INFINITE );

// Clean up
::CloseHandle( hThread );

Interprocess Communications

Áö±Ý±îÁö ¿ì¸®´Â ¿ø°Ý ÇÁ·Î¼¼½º¿¡ DLLÀ» ÁÖÀÔÇÏ´Â ¹ý¿¡ ´ëÇØ¼­¸¸ ³íÇß´Ù. ÇÏÁö¸¸ ´ëºÎºÐÀÇ »óȲ¿¡¼­ ÁÖÀÔµÈ DLLÀº ¿©·¯ºÐÀÇ ¿ø·¡ÀÇ ÀÀ¿ëÇÁ·Î±×·¥°ú ƯÁ¤ ¹æ½ÄÀ¸·Î Åë½ÅÀ» ÇÒ Çʿ䰡 ÀÖÀ» °ÍÀÌ´Ù(ÀÌÁ¦ DLLÀº ¿ì¸®ÀÇ ·ÎÄà ÀÀ¿ëÇÁ·Î±×·¥ÀÌ ¾Æ´Ï¶ó ƯÁ¤ ¿ø°Ý ÇÁ·Î¼¼½º¿¡ map µÇ¾ú´Ù´Â °ÍÀ» »ó±âÇ϶ó). ¿ì¸®ÀÇ Password Spy¸¦ ¿¹·Î µé¾îº¸ÀÚ. DLLÀº ½ÇÁ¦ ÆÐ½º¿öµå¸¦ Æ÷ÇÔÇÏ´Â ÄÁÆ®·Ñ¿¡ ´ëÇÑ ÇÚµéÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. ÀÌ °ªÀº ¸í¹éÈ÷ ÄÄÆÄÀÏ ½Ã¿¡ hardcord µÉ ¼ö°¡ ¾ø´Ù. ¸¶Âù°¡Áö·Î DLLÀÌ ÀÏ´Ü ÆÐ½º¿öµå¸¦ ¾ò¾ú´Ù¸é À̰ÍÀº ¿ì¸®°¡ ÀÌ ÆÐ½º¿öµå¸¦ ÀûÀýÈ÷ µð½ºÇ÷¹ÀÌ ÇÒ ¼ö ÀÖµµ·Ï ¿ì¸®ÀÇ ÀÀ¿ëÇÁ·Î±×·¥À¸·Î Àü¼ÛÇØÁÖ¾î¾ß ÇÑ´Ù.

´ÙÇàÈ÷µµ ÀÌ·± »óȲÀ» ó¸®ÇÏ´Â ¸¹Àº ¹æ¹ýµéÀÌ ÀÖ´Ù. ¸î °¡Áö¸¸ ¿­°ÅÇØº¸¸é File Mapping, WM_COPYDATA, Ŭ¸³º¸µå ±×¸®°í ¶§¶§·Î´Â ¸Å¿ì ÆíÇÑ #pragma data_seg µîÀÌ ÀÖ´Ù. À̵é Å×Å©´ÐÀº MSDN(Interprocess Communications ÂüÁ¶)À̳ª ´Ù¸¥ Æ©Å͸®¾ó¿¡ Àß ¹®¼­È­µÇ¾î ÀÖÀ¸¹Ç·Î  ¿©±â¼­´Â Ưº°È÷ ¾ð±ÞÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù. ¾î·µç ÇÊÀÚ´Â LibSpy ¿¹Á¦¿¡¼­ ¿ÀÁ÷ #pragma data_seg¸¸ ÀÌ¿ëÇß´Ù.

LibSpy¿Í À̰ÍÀÇ ¼Ò½º´Â ÀÌ ¹®¼­ÀÇ Ã¹ ¸Ó¸®¿¡ ÀÖ´Â ´Ù¿î·Îµå ÆÐŰÁö¿¡¼­ ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù.

III. CreateRemoteThread¿Í WriteProcessMemory Å×Å©´Ð

µ¥¸ð ÀÀ¿ëÇÁ·Î±×·¥ : WinSpy

´Ù¸¥ ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£¿¡ ƯÁ¤ Äڵ带 º¹»çÇÑ ÈÄ ÀÌ ÇÁ·Î¼¼½ºÀÇ ÄÁÅØ½ºÆ® ³»¿¡¼­ ½ÇÇàÇÏ´Â ¶Ç ´Ù¸¥ ¹æ¹ýÀº ¿ø°Ý ¾²·¹µå¿Í WriteProcessMemory API¸¦ ÀÌ¿ëÇÏ´Â ¹æ¹ýÀÌ´Ù. µ¶¸³ÀûÀÎ DLLÀ» ÀÛ¼ºÇÏ´Â ´ë½Å ¿ì¸®´Â Äڵ带 ¿ø°Ý ÇÁ·Î¼¼½º¿¡ Á÷Á¢ º¹»çÇÑ ÈÄ(WriteProcessMemory¸¦ ÀÌ¿ëÇÏ¿©) CreateRemoteThread¸¦ ÀÌ¿ëÇÏ¿© À̰ÍÀ» ½ÇÇàÇÑ´Ù.

¸ÕÀú CreateRemoteThreadÀÇ ÇÔ¼ö ¼±¾ðÀ» »ìÆìº¸ÀÚ.

HANDLE CreateRemoteThread(
  HANDLE hProcess,        // ¾²·¹µå¸¦ »ý¼ºÇϰíÀÚ ÇÏ´Â ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ÇÚµé
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // º¸¾È ¼Ó¼º¿¡ ´ëÇÑ Æ÷ÀÎÅÍ
  DWORD dwStackSize,      // ÃʱâÀÇ ¾²·¹µå ½ºÅà ũ±â. ¹ÙÀÌÆ® ´ÜÀ§
  LPTHREAD_START_ROUTINE lpStartAddress,     // ¾²·¹µå ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅÍ
  LPVOID lpParameter,     // »õ ¾²·¹µå¸¦ À§ÇÑ ÀÎÀÚ
  DWORD dwCreationFlags,  // »ý¼º Ç÷¢
  LPDWORD lpThreadId      // ¹ÝȯµÇ´Â ¾²·¹µå ½Äº°ÀÚ¿¡ ´ëÇÑ Æ÷ÀÎÅÍ
);

À̰ÍÀ» CreateThread(MSDN)ÀÇ ÇÔ¼ö ¼±¾ð°ú ºñ±³Çغ¸¸é ¾Æ·¡¿Í °°Àº Â÷ÀÌÁ¡À» ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù.

  • CreateRemoteThread¿¡´Â hProcess ÀÎÀÚ°¡ Ãß°¡ÀûÀ¸·Î ÀÖ´Ù. À̰ÍÀº ¾²·¹µå°¡ »ý¼ºµÉ ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ÇÚµéÀÌ´Ù.
  • CreateRemoteThread¿¡¼­ lpStartAddress ÀÎÀÚ´Â ¿ø°Ý ÇÁ·Î¼¼½º ÁÖ¼Ò °ø°£¿¡¼­ÀÇ ¾²·¹µåÀÇ ½ÃÀÛ ÁÖ¼Ò¸¦ ³ªÅ¸³½´Ù. ÀÌ ÇÔ¼ö´Â ¿ø°Ý ÇÁ·Î¼¼½º¿¡ Á¸ÀçÇØ¾ß ÇϹǷΠ´Ü¼øÇÏ°Ô ·ÎÄà ThreadFunc¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ Àü´ÞÇÒ ¼ö°¡ ¾ø´Ù. ¸ÕÀú ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ÀÌ Äڵ带 º¹»çÇØ¾ß ÇÑ´Ù.
  • µ¿ÀÏÇÏ°Ô lpParameter°¡ °¡¸®Å°´Â µ¥ÀÌÅÍ´Â ¿ø°Ý ÇÁ·Î¼¼½º¿¡ Á¸ÀçÇØ¾ß ÇϹǷΠÀÌ°Í ¿ª½Ã º¹»çÇØÁÖ¾î¾ß ÇÑ´Ù.

ÀÌÁ¦ ÀÌ Å×Å©´ÐÀ» Á¤¸®Çغ¸¸é ¾Æ·¡¿Í °°´Ù.

  1. ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ´ëÇÑ HANDLEÀ» ¾ò´Â´Ù(OpenProces).
  2. ÁÖÀ﵃ µ¥ÀÌÅ͸¦ À§ÇØ ¿ø°Ý ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£¿¡ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù(VirtualAllocEx).
  3. ÇÒ´çµÈ ¸Þ¸ð¸®¿¡ ÃʱâÈ­µÈ INJDATA ±¸Á¶Ã¼ÀÇ º¹»çº»À» ±â·ÏÇÑ´Ù(WriteProcessMemory).
  4. ÁÖÀ﵃ Äڵ带 À§ÇØ ¿ø°Ý ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£¿¡ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù.
  5. ÇÒ´çµÈ ¸Þ¸ð¸®¿¡ ThreadFuncÀÇ º¹»çº»À» ±â·ÏÇÑ´Ù.
  6. CreateRemoteThread¸¦ ÀÌ¿ëÇÏ¿© ThreadFuncÀÇ ¿ø°Ý º¹»çº»À» ½ÃÀÛÇÑ´Ù.
  7. ¿ø°Ý ¾²·¹µå°¡ Á¾·áÇÒ ¶§±îÁö ±â´Ù¸°´Ù(WaitForSingleObject).
  8. ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ °á°ú¸¦ ¾ò´Â´Ù(ReadProcessMemory ¶Ç´Â GetExitCodeThread).
  9. ´Ü°è 2¿Í 4¿¡¼­ ÇÒ´çµÇ¾ú´ø ¸Þ¸ð¸®¸¦ ÇØÁ¦ÇÑ´Ù(VirtualFreeEx).
  10. ´Ü°è 6°ú 1¿¡¼­ ¾ò¾ú´ø ÇÚµéµéÀ» ´Ý´Â´Ù(CloseHandle).

ThreadFunc°¡ ÁöÄÑ¾ß ÇÒ Ãß°¡ÀûÀÎ ÁÖÀÇ»çÇ×

  1. ThreadFunc´Â kernel32.dll°ú user32.dll¿¡ ¾ø´Â ÇÔ¼öµéÀ» È£ÃâÇØ¼­´Â ¾È µÈ´Ù. kernel32¿Í user32¸¸ÀÌ ÇÁ·Î¼¼½º¿¡ Á¸ÀçÇÒ °æ¿ì(user32´Â ¸ðµç À©32 ÇÁ·Î¼¼½º¿¡ map µÇ´Â °ÍÀº ¾Æ´Ï¶ó´Â °Í¿¡ ÁÖÀÇ) ·ÎÄà ÇÁ·Î¼¼½º¿Í ´ë»ó ÇÁ·Î¼¼½º ¸ðµÎ¿¡¼­ µ¿ÀÏÇÑ ·Îµå ÁÖ¼Ò¿¡ ÀÖ´Ù´Â °ÍÀÌ º¸ÁõµÈ´Ù(ºÎ·Ï A ÂüÁ¶). ´Ù¸¥ ¶óÀ̺귯¸®¿¡ ÀÖ´Â ÇÔ¼öµéÀÌ ÇÊ¿äÇÒ °æ¿ì ÁÖÀÔµÈ Äڵ忡 LoadLibrary¿Í GetProcAddressÀÇ ÁÖ¼Ò¸¦ Àü´ÞÇÏ¿© ÁÖÀÔµÈ Äڵ尡 ³ª¸ÓÁö ÀÏÀ» ÀÚüÀûÀ¸·Î ó¸®ÇÏ°Ô ÇÑ´Ù. ¾î¶² ÀÌÀ¯·Ð°¡ ¹®Á¦ÀÇ DLLÀÌ ÀÌ¹Ì ´ë»ó ÇÁ·Î¼¼½º¿¡ map µÇ¾î ÀÖ´Ù¸é LoadLibrary ´ë½Å GetModuleHandleÀ» ÀÌ¿ëÇÒ ¼öµµ ÀÖ´Ù.
    ¸¶Âù°¡Áö·Î ThreadFunc ³»¿¡¼­ ¿©·¯ºÐ ÀÚ½ÅÀÇ ¼­ºê·çƾÀ» È£ÃâÇÏ°í ½Í´Ù¸é °¢ ·çƾÀ» ¿ø°Ý ÇÁ·Î¼¼½º¿¡ °³º°ÀûÀ¸·Î º¹»çÇÑ ÈÄ INJDATA¸¦ ÅëÇÏ¿© À̵éÀÇ ÁÖ¼Ò¸¦ ThreadFunc¿¡°Ô Á¦°øÇØÁØ´Ù.
  2. Á¤Àû stringµéÀ» ÀüÇô ÀÌ¿ëÇÏÁö ¾Ê´Â´Ù. ±× º¸´Ù´Â ¸ðµç stringµéÀ» INJDATA¸¦ ÅëÇÏ¿© ThreadFunc¿¡ Àü´ÞÇÑ´Ù. ±× ÀÌÀ¯´Â ÄÄÆÄÀÏ·¯°¡ ¸ðµç Á¤Àû stringµéÀ» ½ÇÇà ÆÄÀÏÀÇ ".data" ¼½¼Ç¿¡ Áý¾î ³Ö°í Äڵ忡´Â ¿ÀÁ÷ reference(=Æ÷ÀÎÅÍ)¸¸ÀÌ ³²±â ¶§¹®ÀÌ´Ù. ±× °á°ú ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ÀÖ´Â ThreadFuncÀÇ º¹»çº»Àº Á¸ÀçÇÏÁö ¾Ê´Â ¹«¾ùÀΰ¡(Àû¾îµµ ÁÖ¼Ò °ø°£¿¡ ¾ø´Â)¸¦ °¡¸®Å³ °ÍÀÌ´Ù.
  3. /GZ ÄÄÆÄÀÏ·¯ ½ºÀ§Ä¡¸¦ Á¦°ÅÇÑ´Ù. À̰ÍÀº µð¹ö±× ºôµåÀÇ °æ¿ì ±âº»ÀûÀ¸·Î ¼³Á¤µÈ´Ù(ºÎ·Ï B ÂüÁ¶).
  4. ThreadFunc¿Í AfterThreadFunc¸¦ staticÀ¸·Î ¼±¾ðÇϰųª ÁõºÐ ¸µÅ©(incremental linking)À» »ç¿ëÇÏÁö ¾Ê´Â´Ù(ºÎ·Ï C ÂüÁ¶).
  5. ThreadFuncÀÇ Áö¿ª º¯¼ö´Â ÇÑ ÆäÀÌÁö(4kb)º¸´Ù ÀÛ¾Æ¾ß ÇÑ´Ù(ºÎ·Ï D ÂüÁ¶). µð¹ö±× ºôµå¿¡¼­´Â ÀÌ¿ëÇÒ ¼ö ÀÖ´Â 4kb Áß ¾à 10¹ÙÀÌÆ® Á¤µµ°¡ ³»ºÎ º¯¼öµéÀ» À§ÇØ ÀÌ¿ëµÈ´Ù´Â Á¡¿¡ ÁÖÀÇÇ϶ó.
  6. 3°³º¸´Ù ¸¹Àº case ¹®À» °¡Áø switch ºí·ÏÀÌ ÀÖ´Ù¸é ¾Æ·¡¿Í °°Àº ½ÄÀ¸·Î ºÐÇÒÇÑ´Ù.

    switch( expression ) {
        case constant1: statement1; goto END;
        case constant2: statement2; goto END;
        case constant3: statement2; goto END;
    }
    switch( expression ) {
        case constant4: statement4; goto END;
        case constant5: statement5; goto END;
        case constant6: statement6; goto END;
    }
    END:
    

    ¶Ç´Â if-else if ½ÃÄö½º·Î ¼öÁ¤ÇÑ´Ù(ºÎ·Ï E ÂüÁ¶).

ÀÌ ±ÔÄ¢À» ÁöŰÁö ¾Ê´Â´Ù¸é °ÅÀÇ È®½ÇÇÏ°Ô ´ë»ó ÇÁ·Î¼¼½º°¡ crash ÇÒ °ÍÀÌ´Ù. ´ë»ó ÇÁ·Î¼¼½º¿¡¼­ÀÇ ÀÛ¾÷ÀÌ ¿©·¯ºÐÀÇ ÇÁ·Î¼¼½º¿¡¼­¿Í °°ÀÌ µ¿ÀÏÇÑ ÁÖ¼Ò¿¡¼­ ÀϾ´Ù°í °¡Á¤Çؼ­´Â ¾È µÈ´Ù´Â °ÍÀ» ºÐ¸íÈ÷ ±â¾ïÇØ¾ß ÇÑ´Ù(ºÎ·Ï F ÂüÁ¶).

GetWindowTextRemote(A/W)

"¿ø°Ý" ¿¡µðÆ® ÄÁÆ®·Ñ¿¡¼­ ÆÐ½º¿öµå¸¦ ¾ò±â À§ÇØ ÇÊ¿äÇÑ ¸ðµç ±â´ÉµéÀº GetWindowTextRemot(A/W)¿¡ ĸ½¶È­ µÇ¾î ÀÖ´Ù.

int GetWindowTextRemoteA( HANDLE hProcess, HWND hWnd, LPSTR  lpString );
int GetWindowTextRemoteW( HANDLE hProcess, HWND hWnd, LPWSTR lpString );

ÀÎÀÚµé

hProcess

¿¡µðÆ® ÄÁÆ®·ÑÀÌ ¼ÓÇØ ÀÖ´Â ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ÇÚµé

hWnd

ÆÐ½º¿öµå¸¦ Æ÷ÇÔÇÏ´Â ¿¡µðÆ® ÄÁÆ®·Ñ¿¡ ´ëÇÑ ÇÚµé

lpString

ÅØ½ºÆ®¸¦ ¾ò±â À§ÇÑ ¹öÆÛ¿¡ ´ëÇÑ Æ÷ÀÎÅÍ

¹Ýȯ °ª

¹Ýȯ °ªÀº º¹»çµÈ ¹®ÀÚµéÀÇ ¼öÀÌ´Ù.

GetWindowTextRemote°¡ ¾î¶»°Ô ÀÛµ¿ÇÏ´Â Áö¸¦ º¸±â À§ÇØ ÀÌÁ¦ ¼Ò½ºÀÇ ¸î¸î ºÎºÐ(ƯÈ÷ ÁÖÀԵǴ µ¥ÀÌÅÍ¿Í ÄÚµå)À» »ìÆìº¸ÀÚ. ¹Ýº¹ÇÏÁö¸¸ °£´ÜÇÏ°Ô Çϱâ À§ÇØ À¯ÀÌÄÚµå Áö¿øÀÌ Á¦°ÅµÇ¾ú´Ù.

INJDATA

typedef LRESULT     (WINAPI *SENDMESSAGE)(HWND,UINT,WPARAM,LPARAM);

typedef struct {    
    HWND hwnd;                    // ¿¡µðÆ® ÄÁÆ®·Ñ¿¡ ´ëÇÑ ÇÚµé
    SENDMESSAGE  fnSendMessage;   // user32!SendMessageA¿¡ ´ëÇÑ Æ÷ÀÎÅÍ

    char psText[128];    // ÆÐ½º¿öµå¸¦ ¼ö½ÅÇϱâ À§ÇÑ ¹öÆÛ
} INJDATA;

INJDATA´Â ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ÁÖÀԵǴ µ¥ÀÌÅÍ ±¸Á¶Ã¼ÀÌ´Ù. ÇÏÁö¸¸ ±×·¯±â Àü¿¡ ÀÌ ±¸Á¶Ã¼ÀÇ SendMessageA¿¡ ´ëÇÑ Æ÷ÀÎÅÍ´Â ¿ì¸®ÀÇ ÀÀ¿ëÇÁ·Î±×·¥¿¡¼­ ÃʱâÈ­µÇ¾î¾ß ÇÑ´Ù. ¿©±â¿¡¼­ÀÇ Æ®¸¯Àº user32.dllÀº (Á¸ÀçÇÒ °æ¿ì!) ¸ðµç ÇÁ·Î¼¼½º¿¡¼­ Ç×»ó µ¿ÀÏÇÑ ÁÖ¼Ò¿¡ map µÈ´Ù´Â °ÍÀ» ÀÌ¿ëÇÏ´Â °ÍÀÌ´Ù. ±×·¯¹Ç·Î SendMessageAÀÇ ÁÖ¼Òµµ Ç×»ó µ¿ÀÏÇÏ´Ù. À̰ÍÀº ¿ø°Ý ÇÁ·Î¼¼½º·Î À¯È¿ÇÑ Æ÷ÀÎÅͰ¡ Àü´ÞµÇ´Â °ÍÀ» º¸ÁõÇØÁØ´Ù.

ThreadFunc

static DWORD WINAPI ThreadFunc (INJDATA *pData) 
{
    pData->fnSendMessage( pData->hwnd, WM_GETTEXT,    // Get password
                          sizeof(pData->psText),
                          (LPARAM)pData->psText );  
    return 0;
}

// ÀÌ ÇÔ¼ö´Â ThreadFunc µÚÀÇ ¸Þ¸ð¸® ÁÖ¼Ò À§Ä¡¸¦ Ç¥½ÃÇØÁØ´Ù.
// int cbCodeSize = (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
static void AfterThreadFunc (void)
{
}

ThradFuncÀº ¿ø°Ý ¾²·¹µå¿¡ ÀÇÇØ ½ÇÇàµÇ´Â ÄÚµåÀÌ´Ù. Èï¹Ì·Î¿î Á¡Àº ¾Æ·¡¿Í °°´Ù.

  • ThreadFuncÀÇ ÄÚµå Å©±â¸¦ °è»êÇϱâ À§ÇØ AfterThreadFunc°¡ ¾î¶»°Ô ÀÌ¿ëµÇ´Â Áö¿¡ ´ëÇØ ÁÖ¸ñÇ϶ó. ÀϹÝÀûÀ¸·Î À̰ÍÀº ÃÖ¼±ÀÇ ¾ÆÀ̵ð¾î´Â ¾Æ´Ï´Ù. ¿Ö³ÄÇÏ¸é ¸µÄ¿°¡ ¿©·¯ºÐÀÇ ÇÔ¼öµéÀÇ ¼ø¼­¸¦ ¸¶À½´ë·Î ¹Ù²Ü ¼ö Àֱ⠶§¹®ÀÌ´Ù(Áï À̰ÍÀº ThreadFunc¸¦ AfterThreadFunc µÚ¿¡ À§Ä¡ÇÏ°Ô ÇÒ ¼öµµ ÀÖÀ½). ÇÏÁö¸¸ ¿ì¸®ÀÇ WinSpyó·³ ÀÛÀº ÇÁ·ÎÁ§Æ®¿¡¼­´Â ¿©·¯ºÐÀÇ ÇÔ¼öµéÀÇ ¼ø¼­°¡ º¸Á¸µÉ °ÍÀ̶ó´Â °ÍÀ» °ÅÀÇ È®½ÅÇÒ ¼ö ÀÖ´Ù. ÇÊ¿äÇÏ´Ù¸é È®½ÇÈ÷ Çϱâ À§ÇØ /ORDER ¸µÄ¿ ¿É¼ÇÀ» ÀÌ¿ëÇÒ ¼öµµ ÀÖÀ» °ÍÀÌ´Ù. ´õ ÁÁÀº ¹æ¹ýÀº µð½º¾î¼Àºí·¯·Î ThreadFuncÀÇ Å©±â¸¦ ÃøÁ¤ÇÏ´Â °ÍÀÌ´Ù.

ÀÌ Å×Å©´ÐÀ¸·Î ¿ø°Ý ÄÁÆ®·ÑÀ» subclass ÇÏ´Â ¹ý

µ¥¸ð ÀÀ¿ëÇÁ·Î±×·¥ : InjectEx

ÀÌÁ¦ Á¶±Ý ´õ º¹ÀâÇÑ ¹®Á¦ Áï ÀÌ Å×Å©´ÐÀ¸·Î ´Ù¸¥ ÇÁ·Î¼¼½º¿¡ ¼ÓÇÏ´Â ÄÁÆ®·ÑÀ» subclass ÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇϱâ·Î ÇÑ´Ù.

¸ÕÀú ÀÌ ÀÛ¾÷À» ¿Ï¼öÇϱâ À§ÇØ ¿©·¯ºÐÀº ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ¾Æ·¡ÀÇ µÎ °³ÀÇ ÇÔ¼ö¸¦ º¹»çÇØ¾ß ÇÑ´Ù.

  1. ThreadFunc : SetWindowLongÀ» ÅëÇÏ¿© ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ÀÖ´Â ÄÁÆ®·ÑÀ» ½ÇÁ¦·Î subclass ÇÑ´Ù
  2. NewProc : subclass µÈ ÄÁÆ®·ÑÀÇ »õ À©µµ¿ì ÇÁ·Î½ÃÀú

ÇÏÁö¸¸ ÁÖ¿ä ¹®Á¦´Â ¿ø°Ý NewProc¿¡ µ¥ÀÌÅ͸¦ ¾î¶»°Ô Àü´ÞÇϴ°¡ ÇÏ´Â Á¡ÀÌ´Ù. NewProcÀº Äݹé ÇÔ¼öÀÌ¸ç Æ¯º°ÇÑ °¡À̵å¶óÀÎÀ» µû¶ó¾ß ÇϹǷΠ ¿ì¸®´Â ÀÌ ÇÔ¼ö¿¡ ÀÎÀڷμ­ INJDATA¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ´Ü¼øÇÏ°Ô Àü´ÞÇÒ ¼ö°¡ ¾ø´Ù. ´ÙÇàÈ÷µµ ÀÌ ¹®Á¦¸¦ ÇØ°áÇÏ´Â ´Ù¸¥ ¹æ¹ýµéÀÌ Àִµ¥(ÇÊÀÚ´Â 2°³¸¦ ¹ß°ßÇßÀ½) À̵éÀº ¸ðµÎ ¾î¼Àºí¸® ¾ð¾î¿¡ ÀÇÁ¸ÇÑ´Ù. ±×·¡¼­ Áö±Ý±îÁö´Â ¾î¼Àºí¸®¿Í °ü·ÃµÈ °ÍÀ» ºÎ·Ï¿¡ ³Ö¾ú¾ú´Âµ¥ ÀÌ°Í ¾øÀÌ´Â ´õ ÀÌ»ó ³íÀǸ¦ ÁøÇàÇÒ ¼ö°¡ ¾ø¾ú´Ù.

ÇØ°áÃ¥ 1

¾Æ·¡ÀÇ ±×¸²À» º¸±â ¹Ù¶õ´Ù.

The virtual address space

¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ NewProc ¹Ù·Î Á÷Àü¿¡ INJDATA°¡ À§Ä¡ÇÑ´Ù´Â Á¡¿¡ ÁÖ¸ñÇ϶ó. ÀÌ·± ¹æ½Ä¿¡ ÀÇÇØ NewProcÀº ¿ø°Ý ÇÁ·Î¼¼½º ÁÖ¼Ò °ø°£¿¡¼­ÀÇ INJDATAÀÇ ¸Þ¸ð¸® À§Ä¡¸¦ ÄÄÆÄÀÏ ½Ã¿¡ ¾Ë°Ô µÈ´Ù. ´õ Á¤È®ÇϰԴ À̰ÍÀº ÀÚ½ÅÀÇ À§Ä¡¿¡ »ó´ëÀûÀÎ INJDATAÀÇ ÁÖ¼Ò¸¦ ¾È´Ù. ±×¸®°í »ç½Ç »ó À̰ÍÀº ¿ì¸®°¡ ÇÊ¿ä·Î ÇÏ´Â ¸ðµç °ÍÀÌ´Ù. ÀÌÁ¦ NewProcÀº ¾Æ·¡¿Í °°À» °ÍÀÌ´Ù.

static LRESULT CALLBACK NewProc(
  HWND hwnd,       // À©µµ¿ì¿¡ ´ëÇÑ ÇÚµé
  UINT uMsg,       // ¸Þ½ÃÁö ½Äº°ÀÚ
  WPARAM wParam,   // ù ¹øÂ° ¸Þ½ÃÁö ÀÎÀÚ
  LPARAM lParam )  // µÎ ¹øÂ° ¸Þ½ÃÁö ÀÎÀÚ
{
    INJDATA* pData = (INJDATA*) NewProc;  // pData´Â NewProcÀ» °¡¸®Å²´Ù;
    pData--;              // ÀÌÁ¦ pData´Â INJDATA¸¦ °¡¸®Å²´Ù;
                          // ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ INJDATA´Â NewProc ¹Ù·Î Á÷Àü¿¡ ÀÖ´Ù´Â °ÍÀ» »ó±âÇ϶ó;

    //-----------------------------
    // subclassing Äڵ尡 ¿©±â¿¡ ¿Â´Ù
    // ........
    //-----------------------------

    // ¿ø·¡ÀÇ À©µµ¿ì ÇÁ·Î½ÃÀú¸¦ È£ÃâÇÑ´Ù;
    // (¿ø°Ý)ThreadFunc¿¡ ÀÇÇØ fnOldProc(SetWindowLong¿¡ ÀÇÇØ ¹ÝȯµÇ´Â)°¡     
    // ÃʱâÈ­µÇ°í (¿ø°Ý)INJDATA¿¡ ÀúÀåµÈ´Ù;
    return pData->fnCallWindowProc( pData->fnOldProc, 
                                    hwnd,uMsg,wParam,lParam );
}

ÇÏÁö¸¸ ¿©±â¿¡´Â ¾ÆÁ÷ ¹®Á¦°¡ ÀÖ´Ù. ù ¹øÂ° ÁÙÀ» º¸±â ¹Ù¶õ´Ù.

INJDATA* pData = (INJDATA*) NewProc;

ÀÌ·± ¹æ½ÄÀ¸·Î´Â hardcode µÈ °ª(¿ì¸®ÀÇ ÇÁ·Î¼¼½º¿¡¼­ÀÇ ¿øº» NewProcÀÇ ¸Þ¸ð¸® À§Ä¡)ÀÌ pData¿¡ µé¾î°¥ °ÍÀÌ´Ù. À̰ÍÀº ÀüÇô ¿ì¸®°¡ ¿øÇÏ´Â ¹Ù°¡ ¾Æ´Ï´Ù. ¿ì¸®°¡ ¿øÇÏ´Â °ÍÀº ÇöÀçÀÇ NewProcÀÇ À§Ä¡°¡ ¾î¶»´ø °£¿¡ ¿ø°Ý ÇÁ·Î¼¼½º·Î ½ÇÁ¦ÀûÀ¸·Î ¿Å°ÜÁø "ÇöÀçÀÇ" NewProcÀÇ º¹»çº»ÀÇ ¸Þ¸ð¸® À§Ä¡ÀÌ´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ ¿ì¸®´Â ÀÏÁ¾ÀÇ "this Æ÷ÀÎÅÍ"¸¦ ÇÊ¿ä·Î ÇÑ´Ù.

C/C++¿¡¼­´Â ÀÌ ¹®Á¦¸¦ ÇØ°áÇÒ ¹æ¹ýÀÌ ¾øÁö¸¸ ÀζóÀÎ ¾î¼Àºí¸®¸¦ ÀÌ¿ëÇϸé ÀÌ ¹®Á¦¸¦ ÇØ°áÇÒ ¼ö ÀÖ´Ù. ¼öÁ¤µÈ NewProcÀ» »ìÆìº¸ÀÚ.

static LRESULT CALLBACK NewProc(
  HWND hwnd,      // À©µµ¿ì¿¡ ´ëÇÑ ÇÚµé
  UINT uMsg,      // ¸Þ½ÃÁö ½Äº°ÀÚ
  WPARAM wParam,  // ù ¹øÂ° ¸Þ½ÃÁö ÀÎÀÚ
  LPARAM lParam ) // µÎ ¹øÂ° ¸Þ½ÃÁö ÀÎÀÚ
{
    // INJDATA ±¸Á¶Ã¼ÀÇ À§Ä¡¸¦ °è»êÇÑ´Ù;
    // ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ INJDATA´Â NewProc ¹Ù·Î Á÷Àü¿¡ À§Ä¡ÇÑ´Ù´Â °ÍÀ» ±â¾ïÇ϶ó;
    INJDATA* pData;
    _asm {
        call    dummy
dummy:
        pop     ecx         // <- ECX´Â ÇöÀçÀÇ EIP °ªÀ» °¡Áø´Ù
        sub     ecx, 9      // <- ECX´Â NewProcÀÇ ÁÖ¼Ò °ªÀ» °¡Áø´Ù
        mov     pData, ecx
    }
    pData--;

    //-----------------------------
    // subclassing Äڵ尡 ¿©±â¿¡ ¿Â´Ù
    // ........
    //-----------------------------

    // ¿ø·¡ÀÇ À©µµ¿ì ÇÁ·Î½ÃÀú¸¦ È£ÃâÇÑ´Ù
    return pData->fnCallWindowProc( pData->fnOldProc, 
                                    hwnd,uMsg,wParam,lParam );
}

ÀÌÁ¦ ¹«½¼ ÀÏÀÌ ÀϾÀ»±î? °ÅÀÇ ¸ðµç ÇÁ·Î¼¼¼­´Â ½ÇÇàµÉ ´ÙÀ½ ¸í·É¾îÄÚµåÀÇ ¸Þ¸ð¸® À§Ä¡¸¦ °¡¸®Å°´Â Ư¼ö ·¹Áö½ºÅ͸¦ °¡Áö°í ÀÖ´Ù. À̰ÍÀÌ ¼ÒÀ§ 32ºñÆ® ÀÎÅÚ ÇÁ·Î¼¼¼­¿Í AMD ÇÁ·Î¼¼¼­¿¡¼­ EIP·Î Ç¥±âµÇ´Â instruction pointerÀÌ´Ù. EIP´Â Ư¼ö ·¹Áö½ºÅÍÀ̹ǷΠ¹ü¿ë ·¹Áö½ºÅ͵é(EAX, EBX µî)°ú °°ÀÌ ÇÁ·Î±×·¡¹ÖÀûÀ¸·Î Á¢±ÙÇÒ ¼ö°¡ ¾ø´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇϸé EIP¸¦ address Çϰí À̰ÍÀÇ ³»¿ëÀ» ¸í½ÃÀûÀ¸·Î Àаųª º¯°æÇÒ ¼ö ÀÖ´Â OpCode°¡ ¾ø´Ù. ±×·¸Áö¸¸ ±×·³¿¡µµ ºÒ±¸Çϰí EIP´Â JMP, CALL°ú RET°ú °°Àº ¸í·É¾îÄڵ忡 ÀÇÇØ ¾Ï¹¬ÀûÀ¸·Î º¯°æ(±×¸®°í °è¼Ó º¯°æ)ÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î ¼­ºê·çƾ CALL/RET ¸ÞÄ¿´ÏÁòÀÌ 32ºñÆ® ÀÎÅÚ ÇÁ·Î¼¼¼­¿Í AMD ÇÁ·Î¼¼½º¿¡¼­ ¾î¶»°Ô ÀÛµ¿ÇÏ´ÂÁö¸¦ »ìÆìº¸±â·Î ÇÏÀÚ.

¿©·¯ºÐÀÌ ¼­ºê·çƾÀ» È£ÃâÇÒ ¶§(CALLÀ» °æÀ¯ÇÏ¿©) EIP¿¡ ¼­ºê·çƾÀÇ ÁÖ¼Ò°¡ ·Îµå µÈ´Ù. ÇÏÁö¸¸ EIP°¡ ¼öÁ¤µÇ±â Á÷Àü¿¡ À̰ÍÀÇ ±âÁ¸ °ªÀÌ ÀÚµ¿ÀûÀ¸·Î ½ºÅÿ¡ push µÈ´Ù(ÈÄ¿¡ µÇµ¹¾Æ°¡´Â instruction pointer·Î ÀÌ¿ëÇϱâ À§ÇØ). ¼­ºê·çƾÀÇ ³¡¿¡¼­ RET ¸í·É¾îÄÚµå´Â ½ºÅÃÀÇ ²À´ë±â¿¡¼­ popÀ» ÇÏ¿© ÀÌ °ªÀ» EIP·Î ³Ö¾îÁØ´Ù.

ÀÌÁ¦ ¿©·¯ºÐÀº CALL°ú RET¿¡ ÀÇÇØ EIP°¡ ¾î¶»°Ô º¯°æµÇ´ÂÁö¸¦ ¾Ë¾Ò´Âµ¥ ±×·¯¸é ÇöÀç °ªÀº ¾î¶»°Ô ¾òÀ» ¼ö ÀÖÀ»±î?
¾Æ¸¶ CALLÀÌ ½ºÅÿ¡ EIP¸¦ push ÇÑ´Ù´Â °ÍÀ» ±â¾ïÇÒ °ÍÀÌ´Ù. ±×·¯¹Ç·Î ÇöÀçÀÇ °ªÀ» ¾ò±â À§ÇØ "dummy ÇÔ¼ö"¸¦ È£ÃâÇÑ Á÷ÈÄ ½ºÅÿ¡¼­ ¹Ù·Î popÀ» ÇÑ´Ù. ÀÌÁ¦ ¿ì¸®ÀÇ ÄÄÆÄÀÏ µÈ NewProc¿¡¼­ÀÇ Àüü Æ®¸¯¿¡ ´ëÇØ ¼³¸íÇϰڴÙ.

 Address   OpCode/Params   Decoded instruction
--------------------------------------------------
:00401000  55              push ebp            ; NewProcÀÇ ¿£Æ®¸® Æ÷ÀÎÆ®
:00401001  8BEC            mov ebp, esp
:00401003  51              push ecx
:00401004  E800000000      call 00401009       ; *a*    dummy È£Ãâ
:00401009  59              pop ecx             ; *b*
:0040100A  83E909          sub ecx, 00000009   ; *c*
:0040100D  894DFC          mov [ebp-04], ecx   ; mov pData, ECX
:00401010  8B45FC          mov eax, [ebp-04]
:00401013  83E814          sub eax, 00000014   ; pData--;
.....
.....
:0040102D  8BE5            mov esp, ebp
:0040102F  5D              pop ebp
:00401030  C21000          ret 0010
  1. dummy ÇÔ¼ö È£Ãâ. À̰ÍÀº ´Ü¼øÈ÷ ´ÙÀ½ ¸í·É¾îÄÚµå·Î jump ÇÏ¸ç ½ºÅÿ¡ EIP¸¦ push ÇÑ´Ù.
  2. ½ºÅÃÀÇ °ªÀ» ECX·Î pop ÇÑ´Ù. ÀÌ °ªÀº ¿ª½Ã Á¤È®È÷ "pop ECX" ¸í·É¾îÄÚµåÀÇ ÁÖ¼ÒÀÌ´Ù.
  3. NewProcÀÇ  entry point¿Í "pop ECX" ¸í·É¾îÄÚµå »çÀÌÀÇ "°Å¸®"°¡ 9¹ÙÀÌÆ®¶ó´Â °Í¿¡ ÁÖ¸ñÇ϶ó. ±×·¡¼­ NewProcÀÇ ÁÖ¼Ò¸¦ °è»êÇϱâ À§ÇØ ECX¿¡¼­ 9¸¦ »«´Ù.

ÀÌ·± ¹æ½Ä¿¡ ÀÇÇØ NewProcÀº ÀÚ½ÅÀÌ ½ÇÁ¦ ¾î¶² À§Ä¡·Î ¿Å°ÜÁ³´ÂÁö¿¡ °ü°è¾øÀÌ Ç×»ó ÀÚ½ÅÀÇ ÁÖ¼Ò¸¦ °è»êÇÒ ¼ö ÀÖ´Ù. ÇÏÁö¸¸ ¿©·¯ºÐÀÌ ÄÄÆÄÀÏ·¯/¸µÄ¿ ¿É¼ÇÀ» ¹Ù²Ù¸é NewProcÀÇ entry point¿Í "pop ECX" ¸í·É¾îÄÚµå »çÀÌÀÇ °Å¸®°¡ ¹Ù²ð ¼öµµ ÀÖ´Ù´Â Á¡¿¡ À¯ÀÇÇ϶ó. ±×¸®°í ¸±¸®Áî ºôµå¿Í µð¹ö±× ºôµå »çÀÌ¿¡¼­µµ ¿ª½Ã ´Ù¸£´Ù. ÇÏÁö¸¸ Áß¿äÇÑ °ÍÀº ±×·³¿¡µµ ºÒ±¸ÇÏ°í ¿©·¯ºÐÀÌ ÄÄÆÄÀÏ ½Ã¿¡ Á¤È®ÇÑ °ªÀ» ¾Ë°í ÀÖ´Ù´Â Á¡ÀÌ´Ù.

  1. ¸ÕÀú ¿ì¸®ÀÇ ÇÔ¼ö¸¦ ÄÄÆÄÀÏ ÇÑ´Ù.
  2. µð½º¾î¼Àºí·¯·Î Á¤È®ÇÑ °Å¸®¸¦ ¾Ë¾Æ³½´Ù.
  3. ¸¶Áö¸·À¸·Î Á¤È®ÇÑ °Å¸® °ªÀ» °¡Áö°í ´Ù½Ã ÄÄÆÄÀÏ ÇÑ´Ù.

À̰ÍÀº InjectEx¿¡¼­ ÀÌ¿ëµÈ ÇØ°áÃ¥ÀÌ´Ù. InjectEx´Â HookInjEx¿Í À¯»çÇÏ°Ô ½ÃÀÛ ¹öưÀÇ ¿ÞÂÊ, ¿À¸¥ÂÊ ¸¶¿ì½º Ŭ¸¯À» Àüȯ(swap).

ÇØ°áÃ¥ 2

¿ø°Ý ÇÁ·Î¼¼½º ÁÖ¼Ò °ø°£¿¡¼­ NewProc ¹Ù·Î ¾Õ¿¡ INJDATA¸¦ À§Ä¡ÇÏ°Ô ÇÏ´Â ¹æ¹ýÀº ¿ì¸®ÀÇ ¹®Á¦¸¦ ÇØ°áÇÏ´Â À¯ÀÏÇÑ ¹æ¹ýÀº ¾Æ´Ï´Ù. ¾Æ·¡ÀÇ ´Ù¸¥ ¹æ½ÄÀÇ NewProcÀ» »ìÆìº¸ÀÚ.

static LRESULT CALLBACK NewProc(
  HWND hwnd,      // À©µµ¿ì¿¡ ´ëÇÑ ÇÚµé
  UINT uMsg,      // ¸Þ½ÃÁö ½Äº°ÀÚ
  WPARAM wParam,  // ù ¹øÂ° ¸Þ½ÃÁö ÀÎÀÚ
  LPARAM lParam ) // µÎ ¹øÂ° ¸Þ½ÃÁö ÀÎÀÚ
{
    INJDATA* pData = 0xA0B0C0D0;    // dummy °ª

    //-----------------------------
    // subclassing Äڵ尡 ¿©±â¿¡ ¿Â´Ù
    // ........
    //-----------------------------

    // ¿ø·¡ÀÇ À©µµ¿ì ÇÁ·Î½ÃÀú¸¦ È£ÃâÇÑ´Ù
    return pData->fnCallWindowProc( pData->fnOldProc, 
                                    hwnd,uMsg,wParam,lParam );
}

¿©±â¿¡¼­ 0xA0B0C0D0´Â ´Ü¼øÈ÷ ¿ø°Ý ÇÁ·Î¼¼½º ÁÖ¼Ò °ø°£¿¡¼­ÀÇ INJDATAÀÇ ½ÇÁ¦(Àý´ë!) ÁÖ¼Ò¸¦ À§ÇÑ placeholderÀÌ´Ù. ÀÌ ÁÖ¼Ò´Â ÄÄÆÄÀÏ ½Ã¿¡´Â ¾Ë ¼ö ¾ø´Ù´Â °ÍÀ» »ó±âÇϱ⠹ٶõ´Ù. ÇÏÁö¸¸ VirtualAllocEx(INJDATA¸¦ À§ÇÑ)¿¡ ´ëÇÑ È£ÃâÀÌ ÀÌ·ç¾îÁø Á÷ÈÄ¿¡´Â ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ÀÇ INJDATAÀÇ À§Ä¡¸¦ ¾Ë°Ô µÈ´Ù.

¿ì¸®ÀÇ NewProcÀº ¾Æ·¡¿Í °°Àº ½ÄÀ¸·Î ÄÄÆÄÀÏ µÉ °ÍÀÌ´Ù.

 Address   OpCode/Params     Decoded instruction
--------------------------------------------------
:00401000  55                push ebp
:00401001  8BEC              mov ebp, esp
:00401003  C745FCD0C0B0A0    mov [ebp-04], A0B0C0D0
:0040100A  ...
....
....
:0040102D  8BE5              mov esp, ebp
:0040102F  5D                pop ebp
:00401030  C21000            ret 0010

±×·¯¹Ç·Î ÄÄÆÄÀÏ µÈ ÄÚµå(16Áø °ªÀ¸·Î)´Â ´ÙÀ½°ú °°À» °ÍÀÌ´Ù : 558BECC745FCD0C0B0A0......8BE55DC21000.

ÀÌÁ¦ ¾Æ·¡¿Í °°ÀÌ ÁøÇàÇÏ¸é µÉ °ÍÀÌ´Ù.

  1. ´ë»ó ÇÁ·Î¼¼½º¿¡ INJDATA, ThreadFunc¿Í  NewProcÀ» º¹»çÇÑ´Ù.
  2. NewProcÀÇ Äڵ带 º¯°æÇÏ¿© pData°¡ INJDATAÀÇ ½ÇÁ¦ ÁÖ¼Ò¸¦ °¡¸®Å°°Ô ÇÑ´Ù.
    ¿¹¸¦ µé¾î ´ë»ó ÇÁ·Î¼¼½º¿¡¼­ÀÇ INJDATAÀÇ ÁÖ¼Ò(VirtualAllocEx¿¡ ÀÇÇØ ¹ÝȯµÈ °ª)°¡ 0x008a0000À̶ó°í ÇÏÀÚ. ±×·¯¸é ¿ì¸®´Â NewProcÀÇ Äڵ带 ´ÙÀ½°ú °°ÀÌ º¯°æÇÑ´Ù.

    558BECC745FCD0C0B0A0......8BE55DC21000 <- ¿ø·¡ÀÇ NewProc 1
    558BECC745FC00008A00......8BE55DC21000 <- INJDATAÀÇ ½ÇÁ¦ ÁÖ¼Ò¸¦ °¡¸®Å°´Â º¯°æµÈ NewProc

    ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ dummy °ªÀÎ A0B0C0D0À» INJDATAÀÇ ½ÇÁ¦ ÁÖ¼Ò·Î ´ëüÇÑ´Ù. 2
  3. ¿ø°Ý ThreadFuncÀÇ ½ÇÇàÀ» ½ÃÀÛÇϸé À̰ÍÀÌ ¿ø°Ý ÇÁ·Î¼¼½º¿¡¼­ ÄÁÆ®·ÑÀ» subclass ÇÑ´Ù.
©ö ¾î°¼­ ÄÄÆÄÀÏ µÈ Äڵ忡¼­ ÁÖ¼Ò A0B0C0D0°ú 008a0000ÀÌ ¿ª¼øÀ¸·Î º¸ÀÌ´ÂÁö ÀǾÆÇØÇÏ´Â »ç¶÷ÀÌ ÀÖÀ» °ÍÀÌ´Ù. À̰ÍÀº ÀÎÅÚ ÇÁ·Î¼¼¼­¿Í AMD ÇÁ·Î¼¼¼­°¡ ±×µéÀÇ (¸ÖƼ ¹ÙÀÌÆ®) µ¥ÀÌÅ͸¦ Ç¥ÇöÇϱâ À§ÇØ little-endian Ç¥±â¹ýÀ» ÀÌ¿ëÇϱ⠶§¹®ÀÌ´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ ¼ýÀÚÀÇ ÇÏÀ§ ¹ÙÀÌÆ®°¡ ¸Þ¸ð¸®ÀÇ °¡Àå ³·Àº ÁÖ¼Ò¿¡ ÀúÀåµÇ¸ç »óÀ§ ¹ÙÀÌÆ®°¡ °¡Àå ³ôÀº ÁÖ¼Ò¿¡ ÀúÀåµÈ´Ù.
UNIX¶ó´Â ´Ü¾î°¡ 4¹ÙÀÌÆ®¿¡ ÀúÀåµÈ´Ù°í °¡Á¤ÇÏÀÚ. big-endian ½Ã½ºÅÛ¿¡¼­´Â UNIX¶ó°í ÀúÀåµÉ °ÍÀÌ´Ù. ¹Ý¸é little-endian ½Ã½ºÅÛ¿¡¼­´Â XINU·Î ÀúÀåµÉ °ÍÀÌ´Ù.

©÷ ¸î¸î (¾Ç¼º) Å©·¢µéÀº ÀÌ¿Í À¯»çÇÑ ¹æ½ÄÀ¸·Î ½ÇÇà ÆÄÀÏÀÇ Äڵ带 º¯°æÇÑ´Ù. ÇÏÁö¸¸ ÀÏ´Ü ¸Þ¸ð¸®¿¡ ·Îµå µÇ¸é ÇÁ·Î±×·¥Àº ÀÚ½ÅÀÇ Äڵ带 º¯°æÇÒ ¼ö ¾ø´Ù(ÄÚµå´Â ½ÇÇà ÆÄÀÏÀÇ ".text" ¼½¼Ç¿¡ Á¸ÀçÇϴµ¥ ¿©±â´Â ¾²±â ±ÝÁö·Î µÇ¾î ÀÖ´Ù). ±×·³¿¡µµ ºÒ±¸ÇÏ°í ¿ì¸®´Â ¿ì¸®ÀÇ ¿ø°Ý NewProcÀ» º¯°æÇÒ ¼ö ÀÖ´Ù. ¿Ö³ÄÇϸé ÀÌ ÇÔ¼ö´Â ÀÌÀü¿¡ PAGE_EXECUTE_READWRITE permissionÀ» °¡Áø ¸Þ¸ð¸® ºÎºÐ¿¡ º¹»çµÇ¾ú±â ¶§¹®ÀÌ´Ù.

¾ðÁ¦ ÀÌ CreateRemoteThread¿Í WriteProcessMemory Å×Å©´ÐÀ» ÀÌ¿ëÇϴ°¡?

ÄÚµå ÁÖÀÔÀ» À§ÇÑ CreateRemoteThread¿Í WriteProcessMemory Å×Å©´ÐÀº ´Ù¸¥ ¹æ¹ýµé°ú ºñ±³Çغ¼ ¶§ Ãß°¡ÀûÀÎ DLLÀ» ÇÊ¿ä·Î ÇÏÁö ¾Ê´Â´Ù´Â Á¡¿¡¼­ Á» ´õ À¯¿¬¼ºÀÌ ÀÖ´Ù. ºÒÇàÈ÷µµ À̰ÍÀº ´Ù¸¥ ¹æ¹ýµé¿¡ ºñÇØ Á» ´õ º¹ÀâÇϰí Á» ´õ À§ÇèÇϱ⵵ ÇÏ´Ù. ThreadFunc¿¡ ¹«¾ùÀΰ¡ À߸øµÇ¸é ¿ø°Ý ÇÁ·Î¼¼½º°¡ ½±°Ô crash ÇÒ ¼ö(´ëºÎºÐÀÇ °æ¿ì ¹Ýµå½Ã) ÀÖ´Ù(ºÎ·Ï F ÂüÁ¶). ¿ø°Ý ThreadFunc¸¦ µð¹ö±ë ÇÏ´Â °ÍÀº ¾Ç¸ùÀÌ µÉ ¼öµµ ÀÖÀ¸¹Ç·Î ÀÌ Å×Å©´ÐÀº ÃÖ´ë ¸î °³ÀÇ ¸í·É¾îÄڵ带 ÁÖÀÔÇÒ ¶§¸¸ ÀÌ¿ëÇØ¾ß ÇÑ´Ù. ¸¹Àº ÄÚµå Á¶°¢À» ÁÖÀÔÇÏ·Á¸é ¼½¼Ç II¿Í I¿¡¼­ ¼³¸íÇß´ø ¹æ¹ý Áß Çϳª¸¦ ÀÌ¿ëÇϱ⠹ٶõ´Ù.

¹Ýº¹ÇϰǴë WinSpy¿Í InjectEx¿Í À̵éÀÇ ¼Ò½º´Â ÀÌ ¹®¼­ÀÇ Ã¹ ¸Ó¸®¿¡ ÀÖ´Â ´Ù¿î·Îµå ÆÐŰÁö¿¡¼­ ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù.
¡¡

¸¶Ä¡¸é¼­

¸¶Áö¸·À¸·Î Áö±Ý±îÁö ¼³¸íÇØ¿Ô´ø °ÍÀ» Á¤¸®Çغ¸±â·Î ÇÑ´Ù.

OS ÇÁ·Î¼¼½º
I. ÈÅ À©9x¿Í À©NT USER32.DLL1°ú ¸µÅ©ÇÏ´Â ÇÁ·Î¼¼½ºµé¸¸
II. CreateRemoteThread¿Í LoadLibrary À©NT¸¸2 ½Ã½ºÅÛ ¼­ºñ½º4¸¦ Æ÷ÇÔÇÑ ¸ðµç ÇÁ·Î¼¼½ºµé3
III. CreateRemoteThread¿Í WriteProcessMemory À©NT¸¸ ½Ã½ºÅÛ ¼­ºñ½º¸¦ Æ÷ÇÔÇÑ ¸ðµç ÇÁ·Î¼¼½ºµé
  1. ¸í¹éÈ÷ ¸Þ½ÃÁö Å¥°¡ ¾ø´Â ¾²·¹µå´Â ÈÅÀ» °É ¼ö ¾ø´Ù. ±×¸®°í SetWindowsHookEx´Â ½Ã½ºÅÛ ¼­ºñ½º¿Í´Â µ¿ÀÛÇÏÁö ¾Ê´Â´Ù(À̵éÀÌ USER32.DLL°ú ¸µÅ©µÇ¾î ÀÖ´Ù°í ÇÏ´õ¶óµµ).
  2. À©9x¿¡´Â CreateRemoteThreadµµ VirtualAllocExµµ ¾ø´Ù(»ç½Ç »ó À̵éÀº À©9x¿¡¼­ emulate µÉ ¼ö Àִµ¥ À̰ÍÀº ¿À·¡ µÈ ¿¾³¯ À̾߱âÀÌ´Ù).
  3. ¸ðµç ÇÁ·Î¼¼½º = ¸ðµç À©32 ÇÁ·Î¼¼½º + csrss.exe
    °íÀ¯(native)ÀÇ ÀÀ¿ëÇÁ·Î±×·¥µé(smss.exe, os2ss.exe, autochk.exe µî)Àº À©32 API¸¦ ÀÌ¿ëÇÏÁö ¾ÊÀ¸¸ç kernel32.dll¿¡ ´ëÇØ¼­µµ ¸µÅ©ÇÏÁö ¾Ê´Â´Ù. À¯ÀÏÇÑ ¿¹¿Ü´Â À©32 ¼­ºê½Ã½ºÅÛ ÀÚüÀÎ csrss.exeÀÌ´Ù. À̰ÍÀº °íÀ¯(native)ÀÇ ÀÀ¿ëÇÁ·Î±×·¥ÀÌÁö¸¸ À̰ÍÀÇ ¶óÀ̺귯¸®(~winsrv.dll) Áß ÀϺδ kernel32.dllÀ» Æ÷ÇÔÇÑ À©32 DLLµéÀ» ÇÊ¿ä·Î ÇÑ´Ù.
  4. ½Ã½ºÅÛ ¼­ºñ½º(lsass.exe, services.exe, winlogon.exe µî)³ª csrss.exe¿¡ Äڵ带 ÁÖÀÔÇÏ°í ½Í´Ù¸é ¿ø°Ý ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ÇÚµéÀ» ¿­±â(OpenProcess) Àü¿¡ ¿©·¯ºÐÀÇ ÇÁ·Î¼¼½ºÀÇ ±ÇÇÑÀ» "SeDebugPrivilege"·Î ¼³Á¤ÇÑ´Ù(AdjustTokenPrivileges).

ÀÌÁ¦ °ÅÀÇ ³¡³µ´Ù. ÇÑ °¡Áö ´õ ¸í½ÉÇØµÎ¾î¾ß ÇÒ °ÍÀÌ ÀÖ´Ù. ¿©·¯ºÐÀÇ ÁÖÀÔµÈ ÄÚµå´Â ƯÈ÷ ¹«¾ùÀΰ¡ À߸øµÇ¾úÀ» °æ¿ì ´ë»ó ÇÁ·Î¼¼½º¸¦ ½±°Ô ¸ÛûÇÑ »óÅ·Π¸ô¾Æ³Ö´Â´Ù. ºÐ¸íÈ÷ ±â¾ïÇ϶ó. Èû¿¡´Â Ã¥ÀÓÀÌ µû¸¥´Ù!

ÀÌ ¹®¼­ÀÇ ¸¹Àº ¿¹Á¦µéÀÌ ÆÐ½º¿öµå¿¡ °üÇÑ °ÍÀ̹ǷΠ¿©·¯ºÐÀº Zhefu ZhangÀÌ ¾´ Super Password Spy++¸¦ Èï¹Ì·Ó°Ô »ý°¢ÇÒ Áöµµ ¸ð¸¥´Ù. °Å±â¿¡¼­ ±×´Â ÀÎÅÍ³Ý ÀͽºÇ÷η¯ ÆÐ½º¿öµå Çʵ忡¼­ ÆÐ½º¿öµå¸¦ ¾ò¾î¿À´Â ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇÑ´Ù. ´õ±¸³ª ±×·± °ø°Ýµé·ÎºÎÅÍ ¿©·¯ºÐÀÇ ÆÐ½º¿öµå ÄÁÆ®·ÑµéÀ» º¸È£ÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼­µµ º¸¿©ÁØ´Ù.

Ã߽Š: ¹®¼­¸¦ ÀÛ¼ºÇϰí ÃâÆÇÇÏ´Â »ç¶÷ÀÌ ¹Þ´Â À¯ÀÏÇÑ º¸»óÀ̶õ ±×°¡ ¹Þ°Ô µÇ´Â feedbackÀÌ´Ù. ±×·¯¹Ç·Î ÀÌ ¹®¼­°¡ À¯¿ëÇÏ´Ù°í »ý°¢Çϸé comment¸¦ ³²±â°Å³ª ÀÌ ¹®¼­¸¦ vote ÇØÁֱ⠹ٶõ´Ù(ola :)). ±×¸®°í ´õ Áß¿äÇÑ °ÍÀ¸·Î¼­ ¹«¾ùÀΰ¡ À߸øµÇ¾ú°Å³ª ¹ö±×°¡ ÀÖ°í À̰ͺ¸´Ù ´õ ³ªÀº ¹æ¹ýÀÌ ÀÖ´ÙµçÁö ¶Ç´Â ¹º°¡ ¸í·áÇÏÁö ¾ÊÀº °ÍÀÌ ÀÖ´Ù¸é ÇÊÀÚ¿¡°Ô ¾Ë·ÁÁֱ⠹ٶõ´Ù.

°¨»çÀÇ ¸»

¸ÕÀú ÀÌ "¹®¼­"°¡ óÀ½À¸·Î ÃâÆÇµÇ¾ú´ø CodeGuruÀÇ µ¶ÀÚ ¿©·¯ºÐ²² °¨»ç µå¸°´Ù. ÀÌ ¹®¼­°¡ ÃʱâÀÇ 1200 ´Ü¾î Á¤µµÀÇ Å©±â¿¡¼­ ÇöÀçÀÇ 6000 ´Ü¾îÀÇ Å©±â·Î Ä¿Áö°Ô µÇ¾ú´ø °ÍÀº ÁÖ·Î ¿©·¯ºÐÀÇ Áú¹®µé ¶§¹®À̾ú´Ù. ÇÏÁö¸¸ ƯÈ÷ Æò°¡ÇÒ ¸¸ÇÑ ÇÑ »ç¶÷¸¸ Ã߸°´Ù¸é ±×´Â Rado PichaÀÌ´Ù. ÀÌ ¹®¼­ÀÇ ¸¹Àº ºÎºÐµéÀº ±×ÀÇ Á¦¾ð°ú ¼³¸íÀ¸·ÎºÎÅÍ µµ¿òÀ» ¹Þ¾Ò´Ù. ¸¶Áö¸·À¸·Î ¿µ¾î¶ó´Â º¹º´À¸·ÎºÎÅÍ ÇÊÀÚ¸¦ µµ¿ÍÁÖ¾î ÀÌ ¹®¼­¸¦ Á» ´õ Àб⠽±°Ô ¸¸µé¾îÁØ Susan Moore¿¡°Ô °¨»ç µå¸°´Ù.

ºÎ·Ï

A) ¾î°¼­ kernel32.dll°ú user32.dllÀº Ç×»ó °°Àº ÁÖ¼Ò¿¡ map µÇ´Â°¡?

ÇÊÀÚÀÇ ÃßÁ¤ : ¸¶ÀÌÅ©·Î¼ÒÇÁÆ® ÇÁ·Î±×·¡¸Ó°¡ ÀÌ·¸°Ô Çϸé À¯¿ëÇÑ ¼Óµµ ÃÖÀûÈ­ ¼ö´ÜÀÌ µÉ ¼ö ÀÖ´Ù°í »ý°¢Ç߱⠶§¹®¿¡. ±× ÀÌÀ¯´Â ¾Æ·¡¿Í °°´Ù.

ÀϹÝÀûÀ¸·Î ½ÇÇà ÆÄÀÏÀº ".reloc" ¼½¼ÇÀ» Æ÷ÇÔÇÑ ¿©·¯ °³ÀÇ ¼½¼ÇÀ¸·Î ±¸¼ºµÇ¾î ÀÖ´Ù.

¸µÄ¿°¡ EXE ÆÄÀÏÀ̳ª DLL ÆÄÀÏÀ» »ý¼ºÇÒ ¶§ À̰ÍÀº ÆÄÀÏÀÌ ¸Þ¸ð¸®ÀÇ ¾îµð¿¡ map µÉ °ÍÀÎÁö¸¦ °¡Á¤ÇÑ´Ù. À̰ÍÀÌ ¼ÒÀ§ °¡Á¤µÈ/¼±È£µÇ´Â ·Îµå/º£À̽º ÁÖ¼ÒÀÌ´Ù. À̹ÌÁö¿¡¼­ ¸ðµç Àý´ë ÁÖ¼ÒµéÀº ÀÌ ¸µÄ¿¿¡ ÀÇÇØ °¡Á¤µÈ ·Îµå ÁÖ¼Ò¸¦ ±â¹ÝÀ¸·Î ÇÑ´Ù. ¾î¶² ÀÌÀ¯·Îµç À̹ÌÁö°¡ ÀÌ ÁÖ¼Ò·Î ·Îµå µÇÁö ¸øÇÒ °æ¿ì PE(Portable Executable) ·Î´õ´Â À̹ÌÁöÀÇ ¸ðµç Àý´ë ÁÖ¼ÒµéÀ» fix ÇØ¾ß ÇÑ´Ù. ÀÌ ¶§¹®¿¡ ".reloc" ¼½¼ÇÀÌ ÀÖ´Â °ÍÀÌ´Ù. À̰ÍÀº À̹ÌÁöÀÇ ¸ðµç À§Ä¡µé¿¡ ´ëÇÑ ¸®½ºÆ®¸¦ Æ÷ÇÔÇϴµ¥ ¿©±â¿¡¼­ ¸µÄ¿ÀÇ °¡Á¤µÈ ·Îµå ÁÖ¼Ò¿Í ½ÇÁ¦ÀÇ ·Îµå ÁÖ¼Ò°£ÀÇ Â÷À̰¡ °¡°øµÉ Çʿ䰡 ÀÖ´Ù(¾î·µç ÄÄÆÄÀÏ·¯¿¡ ÀÇÇØ »ý¼ºµÇ´Â ´ëºÎºÐÀÇ ¸í·É¾îÄÚµåµéÀº ÀÏÁ¾ÀÇ »ó´ë ÁÖ¼Ò¸¦ ÀÌ¿ëÇϹǷΠ»ý°¢º¸´Ù´Â ±×·¸°Ô ¸¹Áö ¾ÊÀº relocationÀÌ ÀϾ´Ù´Â °Í¿¡ ÁÖÀÇÇ϶ó). ¹Ý¸é ·Î´õ°¡ ¸µÄ¿ÀÇ °¡Á¤µÈ ±âº» ÁÖ¼Ò·Î À̹ÌÁö¸¦ ·Îµå ÇÒ ¼ö ÀÖ´Ù¸é ".reloc" ¼½¼ÇÀº ¿ÏÀüÈ÷ ¹«½ÃµÈ´Ù.

±×·±µ¥ ¾î°¼­ kernel32.dll, user32.dll°ú À̵éÀÇ ·Îµå ÁÖ¼ÒµéÀÌ ÀÌ·± ½ºÅ丮¿¡ µü ¸Â¾Æ ¶³¾îÁú±î? ¸ðµç À©32 ÀÀ¿ëÇÁ·Î±×·¥ÀÌ kernel32.dllÀ» ÇÊ¿ä·Î ÇÏ°í ´ëºÎºÐÀÇ ÀÀ¿ëÇÁ·Î±×·¥ÀÌ user32.dllÀ» ÇÊ¿ä·Î ÇϹǷΠÀ̵éÀ» Ç×»ó ±×µé(kernel32 and user32)ÀÇ ¼±È£µÇ´Â ±âº» ÁÖ¼Ò·Î mapping ÇÏ¸é ¸ðµç ½ÇÇà ÆÄÀϵéÀÇ ·Îµå ½Ã°£À» Çâ»óÇÒ ¼ö ÀÖÀ» °ÍÀ̱⠶§¹®ÀÌ´Ù. ±×·¯¸é ·Î´õ´Â kernel32.dll°ú user32.dllÀÇ ÁÖ¼Ò¸¦ ÀüÇô(¿ÏÀüÈ÷) fix ÇÒ Çʿ䰡 ¾øÀ» °ÍÀÌ´Ù.

¾Æ·¡ÀÇ ¿¹Á¦¸¦ Á¦½ÃÇϸ鼭 ÀÌ Åä·ÐÀ» ¸¶Ä¡±â·Î ÇÑ´Ù.

ƯÁ¤ App.exeÀÇ À̹ÌÁö base¸¦ Kernel32(/base:"0x77e80000") ³ª user32(/base:"0x77e10000")ÀÇ ¼±È£µÇ´Â base ÁÖ¼Ò·Î ¼³Á¤ÇÑ´Ù. App.exe°¡ user32¿¡¼­ import¸¦ ÇÏÁö ¾Ê´Â´Ù¸é ´Ü¼øÈ÷ À̰ÍÀ» LoadLibrary ÇÑ´Ù. ±×·± ÈÄ App.exe¸¦ ÄÄÆÄÀÏ Çϰí À̰ÍÀ» ½ÇÇàÇØº¸ÀÚ. ¿¡·¯ ¹Ú½º°¡ Æ¢¾î³ª¿À°í("Illegal System DLL Relocation") App.exeÀÇ ·Îµå°¡ ½ÇÆÐÇÑ´Ù.

¿Ö ±×·²±î? ÇÁ·Î¼¼½º¸¦ »ý¼ºÇÒ ¶§ À©2000, À©XP¿Í À©2003ÀÇ ·Î´õ´Â kernel32.dll°ú user32.dll(À̵éÀÇ À̸§Àº ·Î´õ¿¡ hardcode µÇ¾î ÀÖÀ½)ÀÌ ±×µéÀÇ ¼±È£µÇ´Â base¿¡ map µÇ´ÂÁö¸¦ üũ ÇÑ´Ù. ±×·¸Áö ¸øÇÒ °æ¿ì ÇÏµå ¿¡·¯°¡ ¹ß»ýÇÑ´Ù. À©NT 4¿¡¼­´Â ole32.dllµµ üũ µÈ´Ù. À©NT 3.51 ÀÌÇÏ¿¡¼­´Â ÀÌ·± üũµéÀÌ Á¸ÀçÇÏÁö ¾ÊÀ¸¹Ç·Î kernel32.dll°ú user32.dllÀº ¾î´À À§Ä¡¿¡³ª ¿Ã ¼ö ÀÖ´Ù. Ç×»ó ÀÚ½ÅÀÇ base ÁÖ¼Ò¿¡ ÀÖ¾î¾ß ÇÏ´Â À¯ÀÏÇÑ ¸ðµâÀº ntdll.dllÀÌ´Ù. ·Î´õ´Â À̰ÍÀ» üũ ÇÏÁö ¾ÊÁö¸¸ ntdll.dllÀÌ ÀÚ½ÅÀÇ base¿¡ ¾øÀ¸¸é ÇÁ·Î¼¼½º°¡ »ý¼ºµÉ ¼ö ¾ø´Ù.

¿ä¾àÇÏÀÚ¸é À©NT 4 À̻󿡼­

  • Ç×»ó ÀÚ½ÅÀÇ base ÁÖ¼Ò·Î map µÇ´Â dllµé : kernel32.dll, user32.dll°ú ntdll.dll.
  • ¸ðµç À©32 ÀÀ¿ëÇÁ·Î±×·¥(+ csrss.exe)¿¡ Á¸ÀçÇÏ´Â dllµé : kernel32.dll°ú ntdll.dll.
  • °íÀ¯ÀÇ ÀÀ¿ëÇÁ·Î±×·¥±îÁöµµ Æ÷ÇÔÇÑ ¸ðµç ÇÁ·Î¼¼½º¿¡ Á¸ÀçÇÏ´Â À¯ÀÏÇÑ dll : ntdll.dll.

B) /GZ ÄÄÆÄÀÏ·¯ ½ºÀ§Ä¡

µð¹ö±× ºôµå¿¡¼­ /GZ ÄÄÆÄÀÏ·¯ Ư¼ºÀº ±âº»ÀûÀ¸·Î ÄÑÁø´Ù. ¿ì¸®´Â ¸î¸î ¿¡·¯µéÀ» catch Çϱâ À§ÇØ À̰ÍÀ» ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù(ÀÚ¼¼ÇÑ °ÍÀº ¹®¼­¸¦ ÂüÁ¶). ±×·±µ¥ ¿ì¸®ÀÇ ½ÇÇà ÆÄÀÏ¿¡¼­ À̰ÍÀº ¹«¾ùÀ» ÀǹÌÇϴ°¡?

/GZ ¿É¼ÇÀÌ ÄÑÁ³À» ¶§ ÄÄÆÄÀÏ·¯´Â ¿ì¸®ÀÇ ÇÔ¼ö ³»¿¡¼­ ESP ½ºÅà Æ÷ÀÎÅͰ¡ º¯°æµÇÁö ¾Ê¾Ò´ÂÁö °ËÁõÇÏ´Â ÇÔ¼ö È£Ãâ(¸ðµç ÇÔ¼öÀÇ °ÅÀÇ ³¡¿¡ Ãß°¡µÇ´Â)À» Æ÷ÇÔÇÏ¿© ½ÇÇà ÆÄÀÏ¿¡ Á¸ÀçÇÏ´Â ¸ðµç ÇÔ¼ö¿¡ ´ëÇØ Ãß°¡ÀûÀÎ Äڵ带 Ãß°¡ÇÒ °ÍÀÌ´Ù. ±×·±µ¥ Àá±ñ¸¸. ThreadFunc¿¡ ÇÔ¼ö È£ÃâÀÌ Ãß°¡µÈ´Ù°í? ±×°ÍÀº Àç¾ÓÀ¸·Î °¡´Â ±æÀÌ´Ù. ÀÌÁ¦ ThreadFuncÀÇ ¿ø°Ý º¹»çº»Àº ¿ø°Ý ÇÁ·Î¼¼½º¿¡(Àû¾îµµ °°Àº ÁÖ¼Ò¿¡) Á¸ÀçÇÏÁö ¾Ê´Â ÇÔ¼ö¸¦ È£ÃâÇÒ °ÍÀÌ´Ù.

C) Á¤Àû ÇÔ¼ö ´ë ÁõºÐ ¸µÅ©(Incremental linking)

Incremental linkingÀº ÀÀ¿ëÇÁ·Î±×·¥À» ±¸ÃàÇÒ ¶§ ¸µÅ© ½Ã°£À» ª°Ô Çϱâ À§ÇØ ÀÌ¿ëµÈ´Ù. Á¤»óÀûÀ¸·Î ¸µÅ© µÈ ½ÇÇà ÆÄÀϰú incremetal·Î ¸µÅ© µÈ ½ÇÇà ÆÄÀÏ »çÀÌÀÇ Â÷ÀÌ´Â incremental·Î ¸µÅ© µÈ ½ÇÇà ÆÄÀÏÀÇ °æ¿ì °¢ ÇÔ¼ö È£ÃâÀÌ ¸µÄ¿¿¡ ÀÇÇØ »ý¼ºµÇ´Â Ãß°¡ÀûÀÎ JMP ¸í·É¾îÄÚµå·Î °£´Ù´Â Á¡ÀÌ´Ù(staticÀ¸·Î ¼±¾ðµÈ ÇÔ¼öµéÀº ÀÌ ±ÔÄ¢¿¡ ´ëÇØ ¿¹¿ÜÀÌ´Ù). À̵é JMPµéÀº ÇÔ¼ö¸¦ ÂüÁ¶ÇÏ´Â ¸ðµç CALL ¸í·É¾îÄÚµåµéÀ» °»½ÅÇÏÁö ¾Ê°íµµ ¸µÄ¿°¡ ¸Þ¸ð¸®¿¡¼­ ÇÔ¼öµéÀ» À̵¿ÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÇÏÁö¸¸ ¹®Á¦Á¡À» ¾ß±âÇÏ´Â °Íµµ ¹Ù·Î ÀÌ JMPÀÌ´Ù. ÀÌÁ¦ ThreadFunc¿Í AfterThreadFunc´Â ½ÇÁ¦ÀÇ ÄÚµå ´ë½Å¿¡ JMP ¸í·É¾îÄڵ带 °¡¸®Å³ °ÍÀÌ´Ù. ±×·¡¼­ ¾Æ·¡¿Í °°Àº ½ÄÀ¸·Î ThreadFuncÀÇ Å©±â¸¦ °è»êÇÒ ¶§ 
const int cbCodeSize = ((LPBYTE) AfterThreadFunc - (LPBYTE) ThreadFunc);
À̰ÍÀº »ç½Ç»ó °¢°¢ ThreadFunc¿Í AfterThreadFunc¸¦ °¡¸®Å°´Â JMPµé »çÀÌÀÇ "°Å¸®"¸¦ °è»êÇÒ °ÍÀÌ´Ù(º¸Åë À̵éÀº ¹Ù·Î ¿¬À̾ ³ªÅ¸³¯ °ÍÀÌ´Ù. ÇÏÁö¸¸ À̰ÍÀº °í·ÁÇÏÁö ¸»¶ó). ÀÌÁ¦ ¿ì¸®ÀÇ ThreadFunc´Â ÁÖ¼Ò 004014C0¿¡ ÀÖ°í ¿©±â¿¡ ´ëÇÑ JMP ¸í·É¾îÄÚµå´Â 00401020¿¡ ÀÖ´Ù°í °¡Á¤ÇÏÀÚ.
:00401020   jmp  004014C0
 ...
:004014C0   push EBP          ; ThreadFuncÀÇ ½ÇÁ¦ ÁÖ¼Ò
:004014C1   mov  EBP, ESP
 ...

±×·¯¸é ¾Æ·¡ÀÇ ÄÚµå´Â

WriteProcessMemory( .., &ThreadFunc, cbCodeSize, ..);
¿ø°Ý ÇÁ·Î¼¼½º¿¡ ½ÇÁ¦ÀÇ ThreadFunc°¡ ¾Æ´Ï¶ó "JMP 004014C0" ¸í·É¾îÄÚµå(±×¸®°í ±× µÚ¿¡ ¿À´Â cbCodeSize ¹üÀ§ ³»ÀÇ ¸ðµç ¸í·É¾îÄÚµåµé)¸¦ º¹»çÇÒ °ÍÀÌ´Ù. ¿ø°Ý ¾²·¹µå°¡ ½ÇÇàÇÒ Ã¹ ¹øÂ° ÄÚµå´Â "JMP 004014C0"ÀÏ °ÍÀÌ´Ù. ±×·±µ¥ À̰ÍÀº ¿ø°Ý ¾²·¹µå¸¸ÀÌ ¾Æ´Ï¶ó Àüü ÇÁ·Î¼¼½º¿¡¼­µµ °¡Àå ¸¶Áö¸·ÀÇ ¸í·É¾îÄÚµåµéÀÏ °ÍÀÌ´Ù.

ÇÏÁö¸¸ ÀÌ JMP ¸í·É¾îÄÚµå "±ÔÄ¢"¿¡´Â ¿¹¿Ü°¡ ÀÖ´Ù. ÇÔ¼ö°¡ staticÀ¸·Î ¼±¾ðµÇ¸é incremental·Î ¸µÅ©µÇ¾ú´õ¶óµµ ÇÔ¼ö°¡ Á÷Á¢ È£ÃâµÉ °ÍÀÌ´Ù. ±ÔÄ¢ #4¿¡¼­ ThreadFunc¿Í AfterThreadFunc¸¦ staticÀ¸·Î ¼±¾ðÇϰųª ÁõºÐ ¸µÅ©(incremental linking)À» »ç¿ëÇÏÁö ¾Ê´Â´Ù°í Çß´ø ÀÌÀ¯´Â ÀÌ ¶§¹®ÀÌ´Ù. (incremental linkingÀÇ ¸î °¡Áö ´Ù¸¥ Ãø¸é¿¡ °üÇÑ °ÍÀº Matt PietrekÀÌ ¾´ "Remove Fatty Deposits from Your Applications Using Our 32-bit Liposuction Tools" ¹®¼­¿¡¼­ ¹ß°ßÇÒ ¼ö ÀÖ´Ù)

D) ¾î°¼­ ¿ì¸®ÀÇ ThreadFunc´Â 4kÀÇ Áö¿ª º¯¼ö¹Û¿¡ °¡ÁöÁö ¸øÇÒ±î?

Áö¿ª º¯¼öµéÀº Ç×»ó ½ºÅÿ¡ ÀúÀåµÈ´Ù. ¾î¶² ÇÔ¼ö°¡ ¸»ÇÏÀÚ¸é 256¹ÙÀÌÆ®ÀÇ Áö¿ª º¯¼ö¸¦ °¡Áø´Ù¸é ÇÔ¼ö¿¡ ÁøÀÔÇÒ ¶§(´õ Á¤È®ÇϰԴ ÇÔ¼ö ÇÁ·Ñ·Î±×¿¡¼­) ½ºÅà Æ÷ÀÎÅͰ¡ 256¸¸Å­ °¨¼ÒÇÑ´Ù. ¾Æ·¡ÀÇ ÇÔ¼ö´Â 
void Dummy(void) {
    BYTE var[256];
    var[0] = 0;
    var[1] = 1;
    var[255] = 255;
}

¿¹ÄÁ´ë ¾Æ·¡¿Í À¯»çÇÏ°Ô ÄÄÆÄÀÏ µÈ´Ù.

:00401000   push ebp
:00401001   mov  ebp, esp
:00401003   sub  esp, 00000100           ; ESP¸¦ ÇÊ¿äÇÑ Áö¿ª º¯¼öµéÀ» À§ÇÑ
                                         ; °ø°£¸¸Å­ º¯°æÇÑ´Ù
:00401006   mov  byte ptr [esp], 00      ; var[0] = 0;
:0040100A   mov  byte ptr [esp+01], 01   ; var[1] = 1;
:0040100F   mov  byte ptr [esp+FF], FF   ; var[255] = 255;
:00401017   mov  esp, ebp                ; ½ºÅà Æ÷ÀÎÅ͸¦ º¹¿øÇÑ´Ù
:00401019   pop  ebp
:0040101A   ret

À§ÀÇ ¿¹Á¦¿¡¼­ ½ºÅà Æ÷ÀÎÅÍ(ESP)°¡ ¾î¶² ½ÄÀ¸·Î º¯°æµÇ¾ú´ÂÁö¿¡ ÁÖ¸ñÇ϶ó. ±×·±µ¥ ÇÔ¼ö°¡ Áö¿ª º¯¼ö·Î¼­ 4kb ÀÌ»óÀ» ÇÊ¿ä·Î ÇÑ´Ù¸é ¹«¾ùÀÌ ´Þ¶óÁö´Â °ÍÀϱî? ±×·² °æ¿ì ½ºÅà Æ÷ÀÎÅÍ´Â Á÷Á¢ÀûÀ¸·Î º¯°æµÇÁö ¾Ê´Â´Ù. ±×º¸´Ù´Â ´Ù¸¥ ÇÔ¼ö(stack probe)°¡ È£ÃâµÇ¸ç À̰ÍÀÌ ½ºÅÃÀ» ÀûÀýÇÏ°Ô º¯°æÇÑ´Ù. ÇÏÁö¸¸ ÀÌ Ãß°¡ÀûÀÎ ÇÔ¼ö È£ÃâÀº ºÐ¸íÈ÷ ¿ì¸®ÀÇ ThreadFunc¸¦ "corrupt" ÇÏ°Ô ¸¸µç´Ù. ¿Ö³ÄÇÏ¸é ¿ø°Ý º¹»çº»Àº °Å±â¿¡ ÀÖÁö ¾ÊÀº ¹«¾ùÀΰ¡¸¦ È£ÃâÇÏ·Á°í ÇÒ °ÍÀ̱⠶§¹®ÀÌ´Ù.

¹®¼­¿¡¼­´Â stack probe¿Í /Gs ÄÄÆÄÀÏ·¯ ¿É¼Ç¿¡ ´ëÇØ ¾î¶² ½ÄÀ¸·Î ¾ð±ÞÇϰí ÀÖ´ÂÁö¸¦ »ìÆìº¸ÀÚ.

"/Gssize ¿É¼ÇÀº stack probe¸¦ Á¦¾îÇÒ ¼ö ÀÖ´Â Áøº¸µÈ Ư¼ºÀÌ´Ù. stack probe´Â ÄÄÆÄÀÏ·¯°¡ ¸ðµç ÇÔ¼ö È£Ãâ¿¡ »ðÀÔÇÏ´Â ÀÏ·ÃÀÇ ÄÚµåÀÌ´Ù. Ȱ¼ºÈ­µÇ¾úÀ» °æ¿ì stack probe´Â °ü·ÃµÈ ÇÔ¼öÀÇ Áö¿ª º¯¼öµéÀ» ÀúÀåÇϱâ À§ÇØ ÇÊ¿äÇÑ °ø°£ÀÇ ¾ç¸¸Å­À» ¸Þ¸ð¸®¿¡¼­ ¹«ÇØÇÏ°Ô ¾ò¾î¿Â´Ù.

¾î¶² ÇÔ¼ö°¡ Áö¿ª º¯¼öµéÀ» À§ÇØ size ½ºÅà °ø°£ ÀÌ»óÀ» ÇÊ¿ä·Î ÇÑ´Ù¸é stack probe°¡ Ȱ¼ºÈ­µÈ´Ù. sizeÀÇ ±âº» °ªÀº ÇÑ ÆäÀÌÁöÀÇ Å©±â(80x86 ÇÁ·Î¼¼¼­¿¡¼­´Â 4kb)ÀÌ´Ù. ÀÌ °ªÀº ½ÇÇà ½Ã¿¡ ÇÁ·Î±×·¥ ½ºÅÿ¡ commit µÇ¾ú´ø ¸Þ¸ð¸®ÀÇ ¾çÀ» ´Ã¸®±â À§ÇÑ À©32¿Í À©NT °¡»ó ¸Þ¸ð¸® ¸Å´ÏÀú »çÀÌÀÇ ÁÖÀÇ ±í°Ô Á¶ÀýµÇ´Â »óÈ£ ÀÛ¿ëÀ» Çã¿ëÇØÁØ´Ù."

¸î¸î »ç¶÷Àº À§ÀÇ ¹®Àå "stack probe´Â ... ¸Þ¸ð¸®¿¡¼­ ¹«ÇØÇÏ°Ô ¾ò¾î¿Â´Ù"´Â ¹®ÀåÀ» ÀǾÆÇÏ°Ô »ý°¢ÇÒ °ÍÀ̶ó°í »ý°¢µÈ´Ù. Àúµé ÄÄÆÄÀÏ·Î ¿É¼Çµé(±×µéÀÇ ¼³¸í¿¡ µû¸£¸é!)Àº ±× À̸éÀ» µé¿©´Ù º¸°í ¹«¾ùÀÌ ÁøÇàµÇ°í ÀÖ´ÂÁö¸¦ ¾Ë ¶§±îÁö´Â ¶§¶§·Î ÁøÂ¥ °ñÄ¡ ¾ÆÇÁ´Ù. ¿¹ÄÁ´ë ¾î¶² ÇÔ¼ö°¡ ÀÚ½ÅÀÇ Áö¿ª º¯¼öµéÀ» À§ÇØ 12kbÀÇ °ø°£À» ÇÊ¿ä·Î ÇÑ´Ù¸é ½ºÅÃÀÇ ¸Þ¸ð¸®´Â ¾Æ·¡¿Í °°Àº ½ÄÀ¸·Î "ÇÒ´ç"(´õ Á¤È®ÇϰԴ commit)µÉ °ÍÀÌ´Ù.

sub    esp, 0x1000    ; ù ¹øÂ° 4kb¸¦ "ÇÒ´çÇÑ´Ù"
test  [esp], eax      ; »õ ÆäÀÌÁö¸¦ commit Çϱâ À§ÇØ
                      ; ¸Þ¸ð¸®¸¦ touch ÇÑ´Ù(ÀÌ¹Ì commit µÇÁö ¾Ê¾Ò´Ù¸é)
sub    esp, 0x1000    ; µÎ ¹øÂ° 4kb¸¦ "ÇÒ´çÇÑ´Ù"
test  [esp], eax      ; ...
sub    esp, 0x1000
test  [esp], eax

½ºÅà Æ÷ÀÎÅͰ¡ 4kb ´ÜÀ§·Î ¾î¶»°Ô º¯°æµÇ´ÂÁö¿¡ ÁÖ¸ñÇÏ°í ´õ Áß¿äÇÑ °ÍÀ¸·Î¼­ °¢ ½ºÅÜ ÈÄ¿¡ ¾î¶² ½ÄÀ¸·Î ½ºÅÃÀÇ ¹Ù´ÚÀÌ "touch"  µÇ´ÂÁö(test¸¦ ÅëÇÏ¿©)¿¡ ´ëÇØ ÁÖ¸ñÇϱ⠹ٶõ´Ù. À̰ÍÀº ´Ù¸¥ ÆäÀÌÁö¸¦ "ÇÒ´ç"(committing)Çϱâ Àü¿¡ ½ºÅÃÀÇ ¹Ù´ÚÀ» Æ÷ÇÔÇÏ´Â ÆäÀÌÁö°¡ commit µÇ´Â °ÍÀ» º¸ÁõÇØÁØ´Ù.

¾Æ·¡ÀÇ ³»¿ëÀ» Àо¸é

"°¢°¢ÀÇ »õ·Î¿î ¾²·¹µå´Â commit µÇ°í ¿¹¾àµÈ ¸Þ¸ð¸®·Î ±¸¼ºµÈ ÀÚ±â ÀÚ½ÅÀÇ ½ºÅà °ø°£À» ¹Þ´Â´Ù. ±âº» °ªÀ¸·Î °¢ ¾²·¹µå´Â 1MbÀÇ ¿¹¾àµÈ ¸Þ¸ð¸®¿Í ÇÑ ÆäÀÌÁöÀÇ commit µÈ ¸Þ¸ð¸®¸¦ ÀÌ¿ëÇÑ´Ù. ½Ã½ºÅÛÀº ÇÊ¿äÇÒ ¶§ ¿¹¾àµÈ ½ºÅà ¸Þ¸ð¸®¿¡¼­ ÇÑ ÆäÀÌÁö ºí·ÏÀ» commit ÇÒ °ÍÀÌ´Ù."(MSDN CreateThread > dwStackSize > "Thread Stack Size" ÂüÁ¶).

/Gs¿¡ °üÇÑ ¹®¼­¿¡¼­ ¿©·¯ºÐÀº ¿©·¯ºÐÀÇ ÀÀ¿ëÇÁ·Î±×·¥°ú À©µµ¿ìÁî NT °¡»ó ¸Þ¸ð¸® ¸Å´ÏÀú »çÀÌ¿¡¼­ ÁÖÀÇ ±í°Ô Á¶ÀýµÇ´Â »óÈ£ ÀÛ¿ëÀ» Çã¿ëÇØÁÖ´Â stack probe¸¦ °¡Áø´Ù´Â ¸»À» Çß´ÂÁö°¡ ºÐ¸íÇØÁú °ÍÀÌ´Ù.

ÀÌÁ¦ ¿ì¸®ÀÇ ThreadFunc¿Í 4kb Á¦ÇÑ¿¡ °üÇÑ ³íÁ¡À¸·Î µÇµ¹¾Æ°¡ÀÚ.
ºñ·Ï ¿ì¸®´Â /Gs ¿É¼ÇÀ¸·Î stack probe ·çƾ¿¡ ´ëÇÑ È£ÃâÀ» ¿¹¹æÇÒ ¼ö ÀÖÁö¸¸ ±× ¹®¼­´Â ¿ì¸®°¡ ±×·¸°Ô ÇÏ´Â °Í¿¡ ´ëÇØ °æ°í¸¦ Çϰí ÀÖ´Ù. °Ô´Ù°¡ ±× ¹®¼­´Â #pragma check_stack Áö½ÃÀÚ¸¦ ÀÌ¿ëÇϸé stack probe ±â´ÉÀ» ÄѰ¡³ª ²ø ¼ö ÀÖ´Ù°í ¸»Çϰí ÀÖ´Ù. ÇÏÁö¸¸ ÀÌ pragma´Â stack probe¿¡ ÀüÇô ¿µÇâÀ» ¹ÌÄ¡Áö ¾Ê´Â µíÇÏ´Ù(±× ¹®¼­°¡ À߸ø µÇ¾úµçÁö ÇÊÀÚ°¡ ´Ù¸¥ ¾î¶² »ç½ÇµéÀ» À߸ø ¾È °ÍÀ̰ÚÁö¸¸). ¾î·µç CreateRemoteThread¿Í WriteProcessMemory Å×Å©´ÐÀÌ ÀÛÀº ÄÚµå Á¶°¢µéÀ» ÁÖÀÔÇÒ ¶§¸¸ ÀÌ¿ëµÈ´Ù´Â °ÍÀ» »ó±âÇÑ´Ù¸é ¿ì¸®ÀÇ Áö¿ª º¯¼ö´Â ±â²¯ÇØ¾ß ¸î ¹ÙÀÌÆ® ÀÌ»óÀ» *¼Ò¸ð*ÇÏÁö ¾ÊÀ» °ÍÀÌ¸ç °ÅÀÇ 4kb °æ°è¿¡ ±ÙÁ¢ÇÒ ÀÏÀº ¾øÀ» °ÍÀÌ´Ù.

E) ¾î°¼­ ÇÊÀÚ´Â 3°³º¸´Ù ¸¹Àº case ¹®À» °¡Áø ¿ì¸®ÀÇ switch ºí·ÏÀ» ºÐÇÒÇØ¾ß Çߴ°¡?

¹Ýº¹ÇÏÁö¸¸ ¿¹Á¦·Î ¼³¸íÇÏ´Â °ÍÀÌ °¡Àå ½±´Ù. ¾Æ·¡ÀÇ ÇÔ¼ö¸¦ »ìÆìº¸ÀÚ.
int Dummy( int arg1 ) 
{
    int ret =0;

    switch( arg1 ) {
    case 1: ret = 1; break;
    case 2: ret = 2; break;
    case 3: ret = 3; break;
    case 4: ret = 0xA0B0; break;
    }
    return ret;
}

À̰ÍÀº ¾Æ·¡¿Í À¯»çÇÏ°Ô ÄÄÆÄÀÏ µÉ °ÍÀÌ´Ù.

 Address   OpCode/Params    Decoded instruction
--------------------------------------------------
                                             ; arg1 -> ECX
:00401000  8B4C2404         mov ecx, dword ptr [esp+04]
:00401004  33C0             xor eax, eax     ; EAX = 0
:00401006  49               dec ecx          ; ECX --
:00401007  83F903           cmp ecx, 00000003
:0040100A  771E             ja 0040102A

; Å×À̺íÀÇ ÁÖ¼Ò Áß Çϳª·Î JMP ***
; ECX´Â ¿ÀÇÁ¼ÂÀ» °¡Áø´Ù´Â °Í¿¡ ÁÖ¸ñÇ϶ó
:0040100C  FF248D2C104000   jmp dword ptr [4*ecx+0040102C]

:00401013  B801000000       mov eax, 00000001   ; case 1: eax = 1;
:00401018  C3               ret
:00401019  B802000000       mov eax, 00000002   ; case 2: eax = 2;
:0040101E  C3               ret
:0040101F  B803000000       mov eax, 00000003   ; case 3: eax = 3;
:00401024  C3               ret
:00401025  B8B0A00000       mov eax, 0000A0B0   ; case 4: eax = 0xA0B0;
:0040102A  C3               ret
:0040102B  90               nop

; ÁÖ¼Ò Å×ÀÌºí  ***
:0040102C  13104000         DWORD 00401013   ; case 1·Î Á¡ÇÁ
:00401030  19104000         DWORD 00401019   ; case 2·Î Á¡ÇÁ
:00401034  1F104000         DWORD 0040101F   ; case 3·Î Á¡ÇÁ
:00401038  25104000         DWORD 00401025   ; case 4·Î Á¡ÇÁ

switch-case°¡ ¾î¶»°Ô ±¸ÇöµÇ´ÂÁö¿¡ ÁÖ¸ñÇϱ⠹ٶõ´Ù.
¸ðµç ´ÜÀÏ case ¹®À» µ¶¸³ÀûÀ¸·Î °Ë»çÇϱ⺸´Ù´Â ÁÖ¼Ò Å×À̺íÀÌ »ý¼ºµÈ´Ù. ±×·± ÈÄ ÁÖ¼Ò Å×ÀÌºí¿¡ ´ëÇÑ ¿ÀÇÁ¼ÂÀ» °£´ÜÇÏ°Ô °è»êÇÔÀ¸·Î½á ¿Ã¹Ù¸¥ case·Î Á¡ÇÁÇÑ´Ù. Àß »ý°¢Çغ¸¸é À̰ÍÀº »ç½Ç»ó ±â´É °³¼±À̶ó°í ÇÒ ¼ö ÀÖ´Ù. 50°³ÀÇ case ¹®À» °¡Áø switch ¹®À» °¡Áö°í ÀÖ´Ù°í »ó»óÇØº¸ÀÚ. À§ÀÇ Æ®¸¯ÀÌ ¾ø´Ù¸é ¸¶Áö¸· case¿¡ µµ´ÞÇϱâ À§ÇØ 50°³ÀÇ CMP¿Í JMP ¸í·É¾îÄڵ带 ½ÇÇàÇØ¾ß ÇÑ´Ù. ¹Ý¸é ÁÖ¼Ò Å×À̺íÀÌ ÀÖÀ¸¸é ÇÑ ¹øÀÇ Å×À̺í look-upÀ¸·Î ¾î¶°ÇÑ case¿¡¶óµµ Á¡ÇÁ ÇÒ ¼ö ÀÖ´Ù. ÄÄÇ»ÅÍ ¾Ë°í¸®Áò°ú time complexityÀÇ ¿ë¾î·Î ¸»ÇÏÀÚ¸é ¿ì¸®´Â O(2n) ¾Ë°í¸®ÁòÀ» O(5) ¾Ë°í¸®ÁòÀ¸·Î ´ëüÇÑ °ÍÀÌ´Ù. ¿©±â¿¡¼­ 

  1. O´Â ÃÖ¾ÇÀÇ °æ¿ìÀÇ time complexity¸¦ ³ªÅ¸³½´Ù.
  2. ¿ÀÇÁ¼ÂÀ» °è»êÇϰí Å×À̺í look-upÀ» Çϰí ÃÖÁ¾ÀûÀ¸·Î ÀûÀýÇÑ ÁÖ¼Ò·Î Á¡ÇÁÇϱâ±îÁö 5°³ÀÇ ¸í·É¾îÄÚµå¸é ÃæºÐÇÏ´Ù°í °¡Á¤Çß´Ù.

±×·±µ¥ À§ÀÇ »óȲÀº case »ó¼öµéÀÌ ¿¬¼ÓÀûÀ¸·Î(1, 2, 3, 4) ÁÖÀÇ ±í°Ô ¼±ÅõǾú±â ¶§¹®¿¡ °¡´ÉÇÑ °ÍÀ̶ó°í »ý°¢ÇÏ´Â »ç¶÷µµ ÀÖÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù. ´ÙÇàÈ÷µµ µ¿ÀÏÇÑ ÇØ°áÃ¥ÀÌ ´ëºÎºÐÀÇ Çö½Ç »ýȰÀÇ ¿¹Á¦¿¡µµ Àû¿ëµÉ ¼ö ÀÖ´Ù´Â °ÍÀÌ ÆÇ¸íµÇ¾ú´Ù. ´ÜÁö ¿ÀÇÁ¼Â °è»ê¸¸ÀÌ ¾à°£ ´õ º¹ÀâÇØÁú »ÓÀÌ´Ù. ÇÏÁö¸¸ ¿©±â¿¡´Â µÎ °¡ÁöÀÇ ¿¹¿Ü°¡ ÀÖ´Ù.

  • 3°³º¸´Ù ÀûÀº case ¹®ÀÌ Àְųª
  • case »ó¼öµéÀÌ ¼­·Î ÀüÇô °ü°è°¡ ¾ø´Ù¸é(¿¹. "case 1", "case 13", "case 50" °ú "case 1000")

°á°úÀûÀÎ ÄÚµå´Â ¸ðµç ´ÜÀÏ case »ó¼ö¸¦ CMP¿Í JMP ¸í·É¾îÄڵ带 °¡Áö°í °¢°¢ Á¶»çÇÏ´Â ±ä °úÁ¤À» °ÅÄ£´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ °á°úÀûÀÎ ÄÚµå´Â ¿ì¸®°¡ Á¤»óÀûÀÎ if-else if ½ÃÄö½º¸¦ ÀÌ¿ëÇßÀ» °æ¿ì¿Í º»ÁúÀûÀ¸·Î µ¿ÀÏÇÏ´Ù.

Èï¹Ì·Î¿î Á¡ : ¾î¶² ÀÌÀ¯·Î »ó¼ö Ç¥Çö ½Ä¸¸ÀÌ case ¹®À» µ¿¹ÝÇÒ ¼ö ÀÖ´ÂÁö ÀǾÆÇÏ°Ô »ý°¢Çß´ø ÀûÀÌ ÀÖ´Ù¸é ±× ÀÌÀ¯¸¦ ÀÌÁ¦ ¾Ë¾ÒÀ» °ÍÀÌ´Ù. ÁÖ¼Ò Å×À̺íÀ» »ý¼ºÇϱâ À§ÇØ ÀÌ °ªÀº ¸í¹éÈ÷ ÄÄÆÄÀÏ ½Ã¿¡ ¾Ë·ÁÁ®¾ß Çϱ⠶§¹®ÀÌ´Ù.

´Ù½Ã ¹®Á¦·Î µÇµ¹¾Æ°¡ÀÚ!
ÁÖ¼Ò 0040100CÀÇ JMP ¸í·É¾îÄڵ忡 ÁÖ¸ñÇϱ⠹ٶõ´Ù. 16Áø opcode FF¿¡ ´ëÇØ ÀÎÅÚÀÇ ¹®¼­°¡ ¹¹¶ó°í Çß´ÂÁö¸¦ »ìÆìº¸ÀÚ.

Opcode    Instruction    Description
FF /4     JMP r/m32      Jump near, absolute indirect,
                         address given in r/m32

¾Æ! ¹®Á¦ÀÇ JMP´Â ÀÏÁ¾ÀÇ absolute addressingÀ» ÀÌ¿ëÇÑ´Ù. ´Ù¸¥ ¸»·Î Ç¥ÇöÇØ¼­ operand Áß Çϳª(¿ì¸®ÀÇ °æ¿ì 0040102C)°¡ Àý´ë ÁÖ¼Ò¸¦ ³ªÅ¸³½´Ù. ´õ ÀÌ»ó ¸»ÇÒ Çʿ䰡 ÀÖÀ»±î? ÀÌÁ¦ ¿ø°Ý ThreadFunc´Â ÀÚ½ÅÀÇ switch¸¦ À§ÇÑ ÁÖ¼Ò Å×À̺íÀº 0040102C¿¡ ÀÖ´Ù°í ¸Í¸ñÀûÀ¸·Î »ý°¢ÇÒ °ÍÀ̰í À߸ø µÈ Àå¼Ò·Î JMP ÇÏ¿© È¿°úÀûÀ¸·Î ¿ø°Ý ÇÁ·Î¼¼½º¸¦ crash ÇÒ °ÍÀÌ´Ù.

F) µµ´ëü ¾î°¼­ ¿ø°Ý ÇÁ·Î¼¼½º°¡ crash Çϴ°¡?

¿ì¸®ÀÇ ¿ø°Ý ÇÁ·Î¼¼½º°¡ crash µÈ´Ù¸é À̰ÍÀº Ç×»ó ¾Æ·¡ ¿øÀÎ Áß Çϳª¿¡ ÀÇÇØ ÀϾ °ÍÀÌ´Ù.
  1. ThreadFunc ³»ºÎ¿¡¼­ Á¸ÀçÇÏÁö ¾Ê´Â stringÀ» ÂüÁ¶Çß´Ù.
  2. ThreadFuncÀÇ Çϳª ÀÌ»óÀÇ ¸í·É¾îÄڵ尡 absolute addressingÀ» ÀÌ¿ëÇÑ´Ù(¿¹·Î¼­ Appendix E ÂüÁ¶).
  3. ThreadFunc°¡ Á¸ÀçÇÏÁö ¾Ê´Â ÇÔ¼ö¸¦ È£ÃâÇß´Ù(ÀÌ È£ÃâÀº ÄÄÆÄÀÏ·Î/¸µÄ¿¿¡ ÀÇÇØ Ãß°¡µÇ¾úÀ» ¼ö ÀÖ´Ù). ÀÌ·² °æ¿ì ThreadFunc¸¦ µð½º¾î¼Àºí·¯·Î º¸¸é ¾Æ·¡¿Í °°Àº °ÍÀ» º¼ ¼ö ÀÖÀ» °ÍÀÌ´Ù.
    :004014C0    push EBP         ; ThreadFuncÀÇ entry point
    :004014C1    mov EBP, ESP
     ...
    :004014C5    call 0041550     ; À̰ÍÀº ¿ø°Ý ÇÁ·Î¼¼½º¸¦ crash ÇÒ °ÍÀÌ´Ù
     ...
    :00401502    ret
    

    ¹®Á¦ÀÇ CALLÀÌ ÄÄÆÄÀÏ·¯¿¡ ÀÇÇØ Ãß°¡µÈ °ÍÀ̶ó¸é(/GZ¿Í °°Àº "±ÝÁöµÈ" ½ºÀ§Ä¡°¡ ÄÑÁ® ÀÖ¾ú±â ¶§¹®¿¡) À̰ÍÀº ThreadFuncÀÇ ½ÃÀÛ ºÎºÐÀ̳ª °ÅÀÇ ³¡ ÁöÁ¡ÀÇ ¾îµò°¡¿¡ À§Ä¡ÇÒ °ÍÀÌ´Ù.

¾î·µç CreateRemoteThread¿Í WriteProcessMemory Å×Å©´ÐÀ» ÀÌ¿ëÇÒ ¶§¿¡´Â ¸Å¿ì ÁÖÀÇÇØ¾ß ÇÑ´Ù. ƯÈ÷ ÄÄÆÄÀÏ·¯/¸µÄ¿ ¿É¼ÇÀ» °üÂûÇØ¾ß ÇÑ´Ù. À̵éÀº ¿ì¸®ÀÇ ThreadFunc¿¡ ¹«¾ùÀΰ¡¸¦ ½±°Ô Ãß°¡ÇÒ ¼ö ÀÖ´Ù.

Âü°í ¹®¼­ :

  1. Load Your 32-bit DLL into Another Process's Address Space Using INJLIB by Jeffrey Richter. MSJ May, 1994
  2. HOWTO: Subclass a Window in Windows 95; Microsoft Knowledge Base Article - 125680
  3. Tutorial 24: Windows Hooks by Iczelion
  4. CreateRemoteThread by Felix Kasza
  5. API hooking revealed by Ivo Ivanov
  6. Peering Inside the PE: A Tour of the Win32 Portable Executable File Format by Matt Pietrek, March 1994
  7. Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference

¹®¼­ history

  • July 25, 2003: Article published
  • August 19, 2003: Applied only some minor formatting changes

About Robert Kuster


Sometimes I dream that I could fly a jet fighter or that I could play guitar like the Gipsy Kings. While I then always realize that bombing people probably isn't so cool, I'm still not so sure about the Gipsy Kings and the guitar. Still, I think writing code is the next best thing that I could do so I will try to make the best out of it.
Currently I am working at Nero AG in Germany and am a postgraduate student at the Faculty of Computer and Information Science in Ljubljana, Slovenia. While my English is still far from perfect, I pretend to speak more or less fluently Slovenian, Bosnian, and German.

Because I'm quite busy at the moment I don't attend to answer any programming questions in the near future . Sorry.

Click here to view Robert Kuster's online profile.


Other popular articles:

[Top] ¡¡
FAQ  Noise tolerance    Search comments  
¡¡ View    Per page ¡¡
New thread Msgs 1 to 50 of 207 (Total: 207) (Refresh) First Prev Next     
Subject  Author  Date 
  Dialog Message pump injection   ted clark  17:43 1 Aug '05 
 
I was wondering if anyone had tried to modify threadfunc to provide for a rudimentary dialog and message pump?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  SendMessage from injected ThreadFunc fails!   dc_2000  17:10 22 Jul '05 
 
It's a great example of how to inject a code into another process but I've encountered one problem that you should mention here. I need to send a variable length memory array back to the main app (WinSpy's window in your case) so I can't use ReadProcessMemory (as I don't know the size of it, since it's allocated in the injected code). I decided to use WM_COPYDATA to transfer it since it worked fine with hooks. Interestingly it crashed the target process.

Later on I researched this issue and it turns out that every message sent by SendMessage from injected code snippet (ThreadFunc in your example) back to WinSpy (of course using pData->fnSendMessage pointer) crashes the target process. Only PostMessage succeeds, but to use it one needs synchronization.

Any ideas why?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Combo Box   rsmith_abq  21:08 12 Jul '05 
 
I have a trading application called Amibroker that allows me to view various stock charts. And a combo box without a tab stop allows me to select the ticker I want (the combo box has roughly 80 tickers loaded). I would like to change tickers in this combo box by voice activation. And so far all I can do is modify the text in the combo box remotely. This does not select a ticker. Will your inject code help me select a ticker remotely and please give me some direction because your article was a little intense.

Robert
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  kernel32 Unconfirmed/Anonymous posting  Anonymous  14:51 11 Jul '05 
 
hi,can someone tell me where i can find informations about how Windows loads kernel32.dll at startup,how it initializes it and if it transfer control in the dll entry point by means of a jump or a call...and in the second case,what parameters are pushed on the stack.

and another thing:does the EntryPoint in a dll file coincides with the address of the DllMain() function?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  So how about Win95/98/Me   dc_2000  12:03 5 Jul '05 
 
Great article but there's still a question about Win9x systems -- it doesn't work there! As someone pointed out before the only hook that is responding on Win9x is WH_CBT but how can you trigger it if all it takes are system messages?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Remote function.   AbsoluteMonkey  14:49 30 Jun '05 
 
IS there no way to call a function residing in the remote exe? Like if the remote exe has a function named "RAD_MP3" and I want to pass a var to it and get the return?

-AbsoluteMonkey

...Crowded elevators smell different to midgets
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  what shoud i do ? Unconfirmed/Anonymous posting  Anonymous  5:26 22 Jun '05 
 
what shoud i do if the created remote thread could not work whereas this thread already existed in the injected process such as iexplorer.exe
¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Similar injection for .NET   Oleg Kobchenko  0:46 11 Jun '05 
 
Similar injection for .NET

I was recently wondering that it would be cool
to hook up to a .NET program, like you do or like
the Spy++ does enumerating controls.

The advantage in .NET is that all objects are
browsable and live. Plus the code is browsable.

So the question is, how from a window handle can
I get the corresponding .NET component?

--
Oleg Kobchenko
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Similar injection for .NET   Get.Well  8:15 14 Jun '05 
 
That would be something really cool.

getWell
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Windows 2003 prohibits hooking on some windows Unconfirmed/Anonymous posting  Anonymous  10:03 9 Jun '05 
 
Hello

First: Thanks for the great article.

I have a strange problem.

I'm writing an automation program which scans all top level windows which are currently open and visible
and searches a specific window, which was created by Install Shield Wizard and then my app simulates user clicks on it.
While doing this scan suddenly the complete Install Shield Setup disappears from the screen at the moment when I try to hook ONE specific window.

I'm using your HookSpy method.
This works PERFECT.
With only one exception:

Only under Windows 2003 (no service pack) and only with ONE dialog which is created by the InstallShield Wizard (setup.exe) Windwos 2003
aborts the install executable.
It is only ONE dialog (class "#32770") which causes this problem.

At the next LogOn Windows 2003 displays:
Setup.exe encountered a problem and needed to close.
Error Signature: AppName: Setup.exe, ModName:user32.dll, ModVer: 5.2.3790.0, Offset: 6711

This is 100% reproduceable.
Under Windows 2000 this does not happen.


I've put debug traces into the code to locate the problem :

BOOL InjectHookDll(HWND h_Wnd)
{
OutputWindowProperties("Start InjectHookDll", h_Wnd); // display infos about h_Wnd

......

UINT u32_ThrID = GetWindowThreadProcessId(h_Wnd, 0);
if (!u32_ThrID)
{
OutputDebugString("Error GetWindowThreadProcessId");
return FALSE;
}

OutputDebugString("Before SetWindowsHookEx");

gh_Hook = SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)HookProc, mh_Dll, u32_ThrID);
if (!gh_Hook)
{
OutputDebugString("Error SetWindowsHookEx");
return FALSE;
}

OutputDebugString("After SetWindowsHookEx");

::SendMessageA(h_Wnd, WM_HOOKSPY, 0,0);

OutputDebugString("After SendMessage");

.....

OutputDebugString("End InjectHookDll");
return TRUE;
}


Additionally BOOL APIENTRY DllMain() outputs Dll_Attach and Dll_Detach
and the Hook procedure outputs all received messages via OutputDebugString().
________________________________________________

Here is the output from Sysinternals DebugView:


12:50:42 [2976] ---------------------
12:50:42 [2976] Start InjectHookDll(hWnd= 0x301B4, Style=0x94CA00CC, Enabled=1, Class="#32770", Caption="Server Installation", X=260, Y=195, CX=504, CY=379)
12:50:42 [2976] Before SetWindowsHookEx
12:50:42 [2976] After SetWindowsHookEx
12:50:42 [1868] HOOKDLL_PROCESS_ATTACH
12:50:42 [1868] ----> HookProc(Msg = A)
12:50:42 [1868] ----> HookProc(Msg = 135)
12:50:42 [1868] ----> HookProc(Msg = 135)
12:50:42 [1868] ----> HookProc(Msg = 4E)
12:50:42 [1868] ----> HookProc(Msg = 4E)
12:50:42 [1868] ----> HookProc(Msg = E)
12:50:42 [1868] ----> HookProc(Msg = D)
12:50:42 [1868] ----> HookProc(Msg = A)
12:50:42 [1868] ----> HookProc(Msg = 7F)
12:50:42 [1868] ----> HookProc(Msg = 7F)
12:50:42 [1868] ----> HookProc(Msg = 7F)
12:50:42 [1868] ----> HookProc(Msg = 7F)
12:50:42 [1868] ----> HookProc(Msg = 7F)
12:50:42 [1868] ----> HookProc(Msg = 7F)
12:50:42 [1868] ----> HookProc(Msg = C14C)
12:50:42 [2976] After SendMessage
12:50:42 [2976] End InjectHookDll
12:50:42 [2976] ---------------------
12:50:42 [2976] Start InjectHookDll(hWnd= 0x30204, Style=0x940008C4, Enabled=1, Class="#32770", Caption="", X=362, Y=336, CX=300, CY=68)"
12:50:42 [2976] Before SetWindowsHookEx
12:50:42 [2976] After SetWindowsHookEx
12:50:44 [1868] ----> HookProc(Msg = 2)
12:50:44 [1868] ----> HookProc(Msg = 82)
12:50:50 [2976] After SendMessage
12:50:50 [2976] End InjectHookDll
12:50:50 [2976] ---------------------



Process 2976 is my application
First the window 301B4 is hooked without any problems.
The dll attaches to the process 1868 which is setup.exe.

WM_HOOKSPY is C14C
When the Hookproc receives this message it calls UnhookWindowsHookEx(gh_Hook);

Then (before the DLL has detached) another window (30204) of the same process (1868) is hooked.

There you see a strange pause of 2 seconds in which windows sends WM_DESTROY (2) and WM_NCDESTROY (82)
to the window and in the next 6 seconds Windows 2003 kills the process.
WM_HOOKSPY (C14C) never arrives in the HookProc.
InjectHookDll requires totally 8 seconds to execute !!

This ALWAYS happens AFTER SetWindowsHookEx() has returned a non-null handle
in that moment when SendMessageA(WM_HOOKSPY) is executed although the Hook.Dll is already in the destination process.

But it also crashes when the Dll has not been hooked before!

____________________

I don't expect any solution here.
But may be anybody has an idea what might be the cause.

Is there a way for a window to prohibit hooking ?
If so how can I find out if a windows prohibits hooking BEFORE Windwos 2003 kills the process ??


Starwalker


¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Re: Windows 2003 prohibits hooking on some windows Unconfirmed/Anonymous posting  Anonymous  13:19 10 Jun '05 
 
Hello

I finally found the reason for the strange behaviour and a workaround!

Studying more debug output I found that it may happen that the problematic window is hooked successfully once and the second time (my program scans every 2 seconds) the crash happens.

This problematic window (something like a splash screen) is only for some seconds on the screen then it is closed by the application (Setup.exe)

It seems that the trial to hook the window when it is going to be destroyed causes the crash under Windows 2003.

This is a big problem because you cannot know this before you try to hook it.
So if you scan all open windows it can ALWAYS happen that any window is going to be destroyed just in the momment when you want to hook it.

The workauround I found is not logic but it works in my case :

Sending any unimportant message (e.g. WM_NCHITTEST) to the window BEFORE calling SetWindowsHookEx() solved the problem:

The crashes are gone but the debug output shows that still the HookProc is NOT called.

I cannot explain why this functions but it does !

Starwalker
¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Send Refresh to a Window Unconfirmed/Anonymous posting  Jessica Lampe  9:38 6 Jun '05 
 
Hello,

I have the following question:

Who can I send a refresh message (like the key input F5) to another window/application?

I would not use a dll and perform this action via WriteProcessMemory and CreateRemoteThread.
It should work for all windows.

Could you show me what I have to change in the NewProc-function of InjCode.cpp to solve this problem?

Thanks!
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Send Refresh to a Window Unconfirmed/Anonymous posting  Anonymous  9:16 9 Jun '05 
 
Hello

F5 is a keystroke.
You don't need any hook at all for that !

F5 has the virtual key code 0x74 (See MSDN !)

Simply write

SendMessage(h_Wnd, WM_KEYDOWN, 0x74, 1);
Sleep (200);
SendMessage(h_Wnd, WM_KEYUP, 0x74, 0xC0000001);

Thats all !

You don't need any hooking for that.

Starwalker

¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Re: Send Refresh to a Window Unconfirmed/Anonymous posting  Jessica Lampe  5:33 10 Jun '05 
 
Hello Starwalker,

thanks for your reply!

I also use PostMessage sometimes to send a keystroke to a window.
But the problem is, that in Internet Explorer for example, the keystroke has to be send to the child window "Internet Explorer_Server".
And all other application have other child windows which react of simulating F5.

I search for a possibility to inject my code in another application and force the refresh of the window without knowing the correct child window.

But call ::InvalidateRect(NULL, NULL, TRUE); or ::RedrawWindow(HWNDWindow, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_NOERASE);
in the injected dll dont'work at all.
The window only blink one time, but there is no refresh.

Does someone know a way to a function, which I have to call for updating the other process?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Send Refresh to a Window Unconfirmed/Anonymous posting  Anonymous  7:43 10 Jun '05 
 
Hello

> I search for a possibility to inject my code in another application
> and force the refresh of the window without knowing the correct child window.

If you don't know which child windows needs the refresh you would have to send an F5 to ALL child windows of the top level window.

But this is not clean programming.
And additionally you can be sure that you will get unwanted side effects if for example any application may react on F5 in another way than you expect. (for example with popping up a search box or any other unwanted action)

The problem is that you will not get further help in this forum because you did not explain EXACTLY and DETAILED what you intend to do !

Why do you want to refresh ALL running applications ?????
That doesn't make sense.

But whatever window you want to refresh you are still wrong here as you do NOT need a hook for that !!

You can send the keystroke from your application directly to the window - without hook.

InvalidateRect only redraws the window and has no effect on the CONTENT of the window.

Starwalker

¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Popular Article   norm.net  4:42 11 May '05 
 
Makes me wonder what people are actually using this for?





My Blog ^



¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Popular Article   Robert Kuster  14:59 18 May '05 
 

Some links referencing WinSpy that I have googled out:

http://www.dotnetmonster.com/Uwe/Forum.aspx/winform-controls/1095/How-to-intercept-messages-sent-to-an-out-process-control
http://www.irisa.fr/triskell/publis/2004/Himdi04a.pdf
http://www.td.unige.ch/wsh/contournement_pfw.pdf
http://actes.sstic.org/SSTIC04/Fingerprinting_integrite_par_timing/SSTIC04-article-Delalleau-Fingerprinting_integrite_par_timing.pdf
http://www.codebreakers-journal.com/include/getdoc.php?id=149&article=70&mode=pdf
http://www.codebreakers-journal.com/include/getdoc.php?id=139&article=65&mode=pdf
http://codeproject.com/win32/AntonioWinLock.asp
http://www.woodmann.net/forum/showthread.php?t=4941
http://www.phrack.org/show.php?p=62&a=12
http://codezine.jp/a/article.aspx?aid=82
http://blog.csdn.net/i_like_cpp/archive/2005/06/03/387032.aspx
http://www.dasomnetwork.com/~leedw/mywiki/moin.cgi/DLL_20injection
http://www.linhadecodigo.com.br/artigos.asp?id_ac=352&pag=1
http://www.pie.pe.kr/cgi-bin/moin.cgi/ThreeWaysToInjectYourCodeIntoAnotherProcess
...

Best Regards,
Robert Kuster
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Thanks for tutor, who can help me to solve in Delphi   SquallLTT  21:56 11 Apr '05 
 
Thanks a lot, but I can't convert that source to Delphi.

¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Greate Work!, and I have a patch for winspy   FireEmissary  2:29 8 Apr '05 
 
The winspy can't capture disable windows.you can add these code to onmousemove:


void onmousemove (HWND hDlg, POINT &pt)
{
HWND child;
HWND hWnd = SmallestWindowFromPoint (pt);

::ScreenToClient (hWnd, &pt);
if((child=ChildWindowFromPointEx (hWnd,pt,CWP_SKIPINVISIBLE|CWP_SKIPTRANSPARENT)))
{
if(child!=hWnd)
hWnd=child;
}

DWORD PID, TID;
.................

thanks your tool.I can capture and copy any windows Text now,save many time
to input....
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Thread injected but crashed?   ya  18:04 17 Mar '05 
 
This is my thread function...

static DWORD WINAPI ThreadFuncAttach(INJECTLIBINFO *pInfo)
{
pInfo->pfnMessageBox(NULL, pInfo->szDllName, pInfo->szDllName, 0);
pInfo->pfnMessageBox(NULL, pInfo->szDllName, pInfo->szDllName, 0);
return 0;
}

I see the messagebox, then after I click ok, that exe crashed. Then I put 2 message box, it still crashes after 1st one.

Any body have idea about it? Thank you in advance!


It's fun to do software sometimes. But for most of time, it's NOT.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  I have translated it into Chinese!   CPAVG  20:15 1 Feb '05 
 
OK, my homepage is ready now, please visit
http://www.farproc.com/Article/ShowArticle.asp?ArticleID=4[^]
to get the Chinese version of this article!!!

电ãáîÜñ«页Íö间£¬Ê¦ÒöêóïÃØ·£¬Ò±ãýìéïá£欢çÊð«õóÝë评ûúëò见£¡£¡

If there is any problem (or CopyRight matter) please notify me!

Coding is my life!
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: I have translated it into Chinese!   Robert Kuster  2:57 3 Feb '05 
 

Umm...Chinese?
No I have nothing against it.
Actually thanks for the translation.

Best Regards,
Robert Kuster
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: I have translated it into Chinese! Unconfirmed/Anonymous posting  Anonymous  21:44 7 Feb '05 
 
Thank you~
¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Please help me.   dSolariuM  1:11 28 Jan '05 
 
Hi,
Very good article:
I want to Inject my dll using second way;
And after injecting (start button)
I want to swap mouse buttons.

2:I use your code in an mfc dialog but it doesn't work!
I create a function by name:bool InjectDll(HANDLE hProcess)
and in it I paste your code and when run it doesn't work
Thanks.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  get process   dSolariuM  0:09 24 Jan '05 
 
Hello,
Very good article:
Now I want to know how can I get a process handle by
giving it's name:
Like Explorer.exe?
Thanks.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: get process Unconfirmed/Anonymous posting  iasen_st  7:44 25 Mar '05 
 
Hi.
As far as I know there is no direct way.You can try this:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID)
where DWORD dwPID is the Process ID of the target process.
If you want to get the PID,
1) use the toolhelp32 api
2) find a handle to the window of the process(in case it has any),and the use GetWindowThreadProcessId(hWnd, &dwPID);
this will put the PID in dwPID.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  None of the three work on Win9x   =[ Abin ]=  22:02 2 Jan '05 
 
::CreateRemoteThread is not supported on Win9x so the 2nd and 3rd ways are immediately out of question, now onto the first way:

HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // thread identifier
);


While works fine on NT plateforms (we won't need to use windows hooks to inject code on NT anyway), the lpfn (hook proc) will never be called if you pass non-zero value to the dwThreadId parameter. MSDN says nothing about this problem but I did some test and found out that, at least Windows 98 second edition did not seem to support thread hooking, so dwThreadId must be zero (system-wide hooking) on Win9x. If you run your demo application on Win98, you will see Explorer.exe crashes.

Even after I used system-wide hooking (I sent messages to the remote process's main window) it did not work either because the DLL that contains the hook proc did not mapped into the remote process, instead, it actually mapped into the calling process (Sounds really funny, I don't understand why it would work that way, just reporting my found) so the code injection was unsuccessful, obviously.

So, I think injecting code on Win9x is really not that simple, lets see:

1, Windows hooks ---- Mystically failed.
2, CreateRemoteThread ---- Unsupported on Win9x.
3, SetThreadContext ---- Requires the thread to be suspended first, ::SuspendThread expecting a handle to the thread (talking about an already-running thread), which comes from a previously successful call to ::OpenThread, and ::OpenThread is unsupported on Win9x.

Of course a lot of programmers are injecting codes on Win9x, but I believe they are using other techniques, I'd really appreciate if you would update your article and share us a solution that works on both Win9x and Win NT plateforms. Thanks.

Edit

Ok I made a mistake on thinking that Win9x doesn't allow thread hooking, in fact it does. The real reason which caused the hook proc never be called is that you used WH_CALLWNDPROC and sent a newly registered window message. I did some more test and found out that on Win9x we better use WH_CBT and send the WM_SYSCOMMAND message to the target window, with a special LPARAM that will never conflict with other "normal" system commands. I've written some code using WH_CBT + WM_SYSCOMMAND, tested it on Win98/2000/XP and worked perfectly well on all of them.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
Score: 1.5 (2 votes).
  Re: None of the three work on Win9x   dc_2000  18:24 4 Jul '05 
 
Hey Abin:

Great comment about Win9x. I encountered the same problem -- my hook works just fine on Windows 2000 but it does nothing on Window Me. You say you used WH_CBT hook and WM_SYSCOMMAND message. I tried it too, but how can you send WM_SYSCOMMAND to trigger that hook without "disturbing" the target window with a false WM_SYSCOMMAND message?

What parameters did you use? Is it just SendMessage? Any help will be greatly appreciated -- I'm stuck here!!!!
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Unmapping after unhooking   ondich  20:45 2 Jan '05 
 
Very instructive article--thank you.

This paragraph is tantalizing:

"The same is true for unmapping the DLL after calling UnhookWindowsHookEx. The DLL isn't really unmapped until an adequate event happens."

This is exactly what I want to force. I want to be able to exit my application (unhooking my system hook before exiting), and then immediately replace the hook DLL with an updated version. When I try this now, the DLL is not yet free to be replaced, because it is still mapped for the other applications running on the system at the time.

Any suggestions on how I can force all the other processes to unmap my DLL when my application quits?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Unmapping after unhooking   ondich  7:39 3 Jan '05 
 
My latest experiment was to use EnumWindows to send a WM_NULL message to each top-level window after I unhook my hook. This seems to be forcing the unmapping of the DLL from all of my running applications. Will this technique be reliable? Dangerous?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Unmapping after unhooking   CPAVG  1:33 27 Jan '05 
 
[quote]EnumWindows to send a WM_NULL message [/quote]
I think it is a good way!

Coding is my life!
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Unmapping after unhooking   riezebosch  4:27 10 Mar '05 
 
Wouldn't a HWND_BROADCAST do the trick?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Problem when using with Notepad.   Peter Hendrix  3:01 10 Dec '04 
 
Hi,

First... great article.

I am using the 'hook-inject' method to hook into notepad (switch the buttons).
hStart = ::FindWindow ("Notepad",NULL);
hStart = ::FindWindowEx (hStart, NULL,"Edit",NULL);


However, when I close notepad the window is closed and the hook should be removed.
I have tried several things, but I constantly get explorer crashes when I quit notepad.

Do you know how to solve this problem?

Kind regards,
Peter.


¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Problem when using with Notepad.   Robert Kuster  12:03 10 Dec '04 
 

Hm..I think your are doing wrong something else
because the Hook itself should cause no crash.

Anyway, you could try to catch the WM_DESTROY message and remove your hook there.
I've described something similar in this posting: What if app closes?[^]

Best Regards,
Robert Kuster
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
Score: 1.0 (1 vote).
  How to do API hooking?   Martin Ng  23:17 9 Dec '04 
 
hi,

Thanks your tutorial,it is really helpful and cool
Btw, I want to know how to use technique you taught here to hook existing API or say system API like winsock, kernel32 blablabla...
I mean,before actual run the original API code,it passes to me first. How?
Thanks.


Martin
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: How to do API hooking?   Robert Kuster  2:45 10 Dec '04 
 

Thanks for your feedback. You can find some good articles about API hooking here:

http://www.codeproject.com/system/hooksys.asp[^]
http://www.internals.com/articles/apispy/apispy.htm[^]
http://research.microsoft.com/sn/detours/[^]

Best Regards,
Robert Kuster
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Generically call back to managed code?   Spunk  11:16 12 Nov '04 
 
I was wondering if there was a way to write a simple DLL that would be able to inject itself into another process and basically act as a RPC server for any method? Rather than worry about copying the DLL into the address space of the process, could it basically have generic code that would listen for a message (or on a socket, named pipe, etc.) to load in a dotnet assembly, build it, then execute it in the remote process? I'm using dotnet as the example because I know you can basically load the assembly into RAM and execute it with ease. Any ideas?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  XP SP2   Alex Korchemniy  2:47 4 Nov '04 
 
Very interesting article. I haven't tested it yet but i have a question...

Does this code work with XP SP2?
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: XP SP2   Robert Kuster  3:19 4 Nov '04 
 

The answer is yes.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Minor Update   riezebosch  7:32 20 Oct '04 
 
Hi,

First: nice article, very useful.

Second: I think you can remove de BOOL in HighLightWindow, because you aren't using it. As far as I can see, you lay an inverse rectangle over the control under the pointer, en when the mouse leaves the control you just re-inverse it. But that is the same action

Or you must be using it to make the usage more clear, but I would prefer to do that in commentary Just my 2 cents.
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: Minor Update   Robert Kuster  12:19 22 Oct '04 
 

A) Thanks for your feedback.
B) The BOOL is indeed redundant.

Best Regards,
RK

¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Keyboard hook Unconfirmed/Anonymous posting  Yalef  7:05 27 Sep '04 
 
Hi,

My Keyboard Hook Dll catches Ctrl+F12, finds my application window, then brings it to foreground and "press" on application button "Stop thread" in order to stop additional thread (not main thread). I have a problem with it, when this application is not active and the thread is running, hooking just does not work (when app is active and the thread is running, everything OK. If you have any idea, please, help.
My code is
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if (((DWORD)lParam & 0x40000000) &&(HC_ACTION==nCode))
{
static prevKey = 0;
if (!prevKey)
prevKey = wParam;

//if Ctlr + F12 are down
if (((prevKey==VK_CONTROL)&&(wParam==VK_F12)) || ((prevKey==VK_F12)&&(wParam==VK_CONTROL)))
{
//look for my application window, open it if it is icon,
//bring it to foreground
EnumWindows(EnumWindowProc, 0);

//look for Stop Thread button of my application and press it
EnumChildWindows(g_hMainWnd, EnumChildProc, 0);

}

}

LRESULT RetVal = CallNextHookEx( hkb, nCode, wParam, lParam );

return RetVal;

}

¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  textSubject:   alex14  3:13 14 Sep '04 
 
Some
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  How to call Kernel32 Functions?   Arsalan Malik  8:05 8 Sep '04 
 
I want RemoteFunction to call a kernel32 function, but I am unable to do so. Remote process always crashes, because it fails to access the address of kernel32 function. As you said, kernel32.dll always load at same address in every process, there should not be any problem to write RemoteFunction as:
static DWORD WINAPI RemoteFunc(LPVOID lpParameter) {
Sleep(100);
return 0;
}

Please tell me any problem with this?

Regards,



Arsalan Malik


¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: How to call Kernel32 Functions?   Robert Kuster  3:38 10 Sep '04 
 

Hi Arsalan,
first consider the following code snippet:
void Func_Explicit()
{
typedef VOID (WINAPI *SLEEP)(DWORD);

SLEEP Sleep = (SLEEP) GetProcAddress (GetModuleHandle("kernel32"),"Sleep");
Sleep (100);
}
In this case you call the Sleep function explicitly (also called run-time dynamic linking). An executable uses the LoadLibrary API to load the DLL at run time (GetModuleHandle can be used if the DLL is already mapped into our address space). After the DLL is loaded, the executable calls the GetProcAddress API to get the actual addresses of the exported DLL function in question. Finally, when the DLL is no longer needed the process can call FreeLibrary to unmap it from its virtual address space.


Now consider the following function:
void Func_Implicit()
{
Sleep (100);
}
This is called Implicit or load-time dynamic linking. All the necessary information about functions (and data) that an executable imports from implicitly linked DLLs, is stored in its ".idata" section. When creating a process, the loader reads this information and loads the appropriate DLLs for you; further, the loader resolves the real addresses of all the imported functions and stores those addresses into the Import Address Table (IAT). Now, whenever you use such a function call the call will go through the IAT table. While kernel32.dll will still be loaded at the same address in every processes, its IAT will differ from one process to another and probably won't be at the same address either. I guess now it should be pretty obvious why your code crashes the remote process...

Final point of interest: If you would peek deep enough inside windows, you would see that at the end the code being executed by the windows loader (while initializing the IAT tables) and by LoadLibrary & GetProcessAddress is the same.

Best Regards,
RK

¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  How to get IAT of Remote Process?   Arsalan Malik  8:01 13 Sep '04 
 
Thankyou for time. Now, problem is that, How can I read IAT of a remote process to determine address of GetModuleHandle function? I need to get kernel32 module handle and then get process address by calling GetProcAddress. Whenever I try to call any of these functions (either implicit or explicit) in remote thread, the remote process crashes. How can I get hold of starting address of any kernel32 function, specially GetModuleHandle to start with.


ARSALAN MALIK

¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: How to get IAT of Remote Process?   Robert Kuster  9:18 14 Sep '04 
 

Hm..why don't you simply pass the address of GetModuleHandle (and so on) to the remote process the same way I've done it with SendMessage in WinSpy? Forget about any IAT tables...

Best Regards,
RK
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: How to get IAT of Remote Process? Unconfirmed/Anonymous posting  Anonymous  14:16 3 Oct '04 
 
I think we should kick IAT out of the door....
We don't need to read the IAT to know what function the remote process has called, but just pay attention to whether the dll has been loaded.
If it does, we can call any function in the dll.
Of course, we should use such a style: GetProcAddress(...).... for safety.


IF someone who very very want to read IAT, I think it will be a boring course.... I think we should read the original exe file .....
We read the PE head.....and so on....
Maybe when you read the IAT finally, you just find the function you want to call doesn't list in the IAT....

¡¡
[Reply][View Thread][Get Link] [Modify|Delete]
  Re: How to get IAT of Remote Process? Unconfirmed/Anonymous posting  Dan Humphrey  12:33 5 Mar '05 
 
Hi. I've tried to do exactly what you mention here - pass the address of GetModuleHandle to the remote process, but it crashes everytime when I attempt to call it. Is there something obvious that I don't understand? Here's a stripped down version of my code:

typedef HMODULE (WINAPI* GetModuleHandleType)(LPCTSTR lpModuleName);

struct SInjData
{
GetModuleHandleType m_fnGetModHandle;
};

static DWORD WINAPI InjectFunc(SInjData* pData)
{
HINSTANCE hKernel = pData->m_fnGetModHandle("kernel32");
return 0;
}

class CInject
{
public:
int InjectCode()
{
CWnd* pWnd = CWnd::FindWindow(NULL, "InjHost"); // Host MFC dialog app

DWORD dwPID;

::GetWindowThreadProcessId(pWnd->m_hWnd, &dwPID);

// Get remote process handle.
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwPID);

try
{
int nRemSize = sizeof(SInjData) + INJ_FUNC_SIZE; // size of compiled function from disassembler (+ an extra bunch to make sure)

unsigned char* pDataRemote = static_cast(VirtualAllocEx(hProcess, 0, nRemSize,
MEM_COMMIT, PAGE_EXECUTE_READWRITE));

DWORD dwBytes;

HINSTANCE hKernel = ::GetModuleHandle("kernel32"); // Loaded by all standard processes

SInjData InjData = { 0 };

InjData.m_fnGetModHandle = (GetModuleHandleType)::GetProcAddress(hKernel, "GetModuleHandleA");

// Fill the remote data structure...
WriteProcessMemory(hProcess, pDataRemote, &InjData, sizeof(SInjData), &dwBytes);

unsigned char* pCodeRemote = pDataRemote + sizeof(SInjData);
DWORD dwThreadID;

WriteProcessMemory(hProcess, pCodeRemote, &InjectFunc, INJ_FUNC_SIZE, &dwBytes);

HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pCodeRemote,
pDataRemote, 0, &dwThreadID);

int nSuccess;
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (PDWORD)&nSuccess);

return nSuccess;
}
catch (...)
{
return 0;
}

return 0;
}
};
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
  Re: How to get IAT of Remote Process? Unconfirmed/Anonymous posting  Dan Humphrey  20:08 6 Mar '05 
 
Never mind about the code issue. I guess I didn't read the appendix on the /GZ compiler flag.

Thanks
¡¡
[Reply][Email][View Thread][Get Link] [Modify|Delete]
Last Visit: 4:16 Sunday 7th August, 2005 First Prev Next