死のOllyDbg-デバッグセッションの動作を保存する

あなたは使用している場合はOllyDbgを(ラベルではなく、あなたがデバッグ情報ているため、独自のアプリケーションをデバッグするために、しかし、リバースエンジニアリングまたはサードパーティの研究のために、あなたの典型的な活動は、他の誰かの製品のマシンコードに踏み込んで起こっている物事の本質を理解し、大量のラベルを配置しています)およびコード全体のコメント、およびデータセクション。プロシージャ/関数および変数の本質を体系的に調査し、それらの目的の理解を反映する名前を付けます。

OllyDbgは、デバッグ、アプリケーションのリバースエンジニアリング、セキュリティメカニズムの調査または回避などに携わるすべての人に紹介する必要はありません。 これは、Windowsに最適なユーザーモードデバッガーの1つですが、多くの欠点と欠点があります。

そして今、数時間(または数日)の作業の後、数百、さらには数千の手順と変数を見つけて署名したとき、OllyDbg突然フリーズまたはクラッシュし、すべての作業が失われます(ラベルやコメントが多数含まれるだけでなく、ブレークポイントや変更が適切な場所に配置される場合もあります)。これは時間の無駄であり、途方もなく意欲をそそる要因であり、そこからあきらめて青ざめます。







この記事では、このような緊急時にOllyDbgを使用して、OllyDbgを(部分的に)すばやくリバースエンジニアリングし、スレッドにぶら下がっているデータを保存し、このような災害が発生した場合のアクションのレシピを作成する方法について説明します。







あなたは記事を読み続けているので、最初からいくつかのことに同意しましょう:







  1. OllyDbg 1.xx, OllyDbg 2.xx, , - , 1.xx ( ).
  2. OllyDbg , , , .. « » —  « », , , , OllyDbg. , , — .
  3. IDA Pro , OllyDbg . Audi « BMW» . — , .
  4. , . « » . howto- , SSH, , , , ? , « BSOD» — , , . ?


«» , , , , , . :







  • (Labels) — OllyDbg , , .
  • (Comments) — .
  • (Breakpoints) — .
  • (Hints) — OllyDbg, , 4 4 , DWORD.


, , , . , , . , , , — - .







, , , , { → } OllyDbg names. .







names PDK
  • NM_LABEL-ユーザー定義のラベル
  • NM_EXPORT-エクスポートされた(グローバル)名前
  • NM_IMPORT-インポートされた名前
  • NM_LIBRARY-ライブラリ、オブジェクトファイル、またはデバッグデータから抽出された名前
  • NM_CONST-ユーザー定義の定数(現在は実装されていません)
  • NM_COMMENT-ユーザー定義のコメント
  • NM_LIBCOMM-ライブラリまたはオブジェクトファイルから自動的に生成されたコメント
  • NM_BREAK-ブレークポイントに関連する条件
  • NM_ARG-アナライザーによってデコードされた引数
  • NM_ANALYSE-アナライザーによって追加されたコメント
  • NM_BREAKEXPR-ブレークポイントに関連する式
  • NM_BREAKEXPL-ブレークポイントに関連する説明
  • NM_ASSUME — Assume function with known arguments
  • NM_STRUCT — Code structure decoded by analyzer
  • NM_CASE — Case description decoded by analyzer
  • NM_PLUGCMD — Plugin commands to execute at breakpoint
  • NM_INSPECT — Several last entered inspect expressions
  • NM_WATCH — Watch expressions


( .udd), — . , - , , , ( ) . , , UDD-, supercool.dll, foo.exe, bar.exe, supercool.dll.









, , OllyDbg ( ). OllyDbg , .







, UDD-? -, , UDD- , . UDD . «Save everything to UDD». «Update .udd file now» — (EXE/DLL/OCX) . , Modules , - . , UDD, . 20 - , UDD , . -, .







4 :







  1. — . BSOD . .
  2. — . , , , , « » « ». ( ?), . . , OllyDbg, , - , .
  3. . OllyDbg . , OllyDbg.exe, . : , OllyDbg «» 27 . , . , OllyDbg, deadlock - Windows, - ( - ). , Microsoft- Spy++, « » , Spy++ GUI- DLL, . - , GUI-. , , . .
  4. OllyDbg UDD-, . UDD- , OllyDbg . , . OllyDbg , , — , , UDD-, . , - . , OllyDbg UDD, UDD-. , UDD- , , , , .  — DLL. OllyDbg «» UDD-, , UDD-, , UDD-. UDD-.




, , , , , , , (..  — ).







UDD — . , , . , . .







UDD :







  1. . , git ( ) ( , ). diff , (, custom diff git). , merge — .
  2. , , . , UDD .


- , . - , , . - ( — , , , , , , ..) - - .







- VCS Git , . : ( WinMain()



), — ( , ). , , . , ( memcpy



, strncat



, qsort



). , , (merge conflict), , . « », .







, - - , , , « », , « », . , , - , , ( , new



).







, - ( ) , , , , .







« »

, , , DAW . : - 5—6 , , , , , . merge, , , — VST- , — - . , , , , git diff



, VST- VST- -.







UDD- - , , OllyDbg, ( ( , ) ) ( ), .

マークアップダンパープラグイン

Markup Dumper, markup —  , . «», — markup, , , .







, ,

OllyDbg, , , . , - . , , - .







@ MODULE OLLYDBG
@ VERSION 1.0.10.0
@ BASEADDR 00400000
@ CHECKSUM 17ca77a5

//
// Section: .text
//

LABEL 0040c214 like_ParseStuff
  CMT 0040c4c5 colon case
  CMT 0040c521 eq case
  CMT 0040c575 checking for 1-byte typespec
  CMT 0040c578 jump if more than 2 byte spec
  CMT 00463f08 checking arg1 (addr) against 0
  CMT 00463f0c EDI = arg2 (type of name)
  CMT 00463f0f goto error if addr==NULL
  CMT 00463f11 checking [addr] against 0
  CMT 00463f15 goto error if 0
...
LABEL 004642fb Insertname_EPILOGUE
LABEL 004a3530 like_memcpy
LABEL 004a36d4 like_strlen
LABEL 004a38bc parse_keyword_1
LABEL 004a6c2c like_sprintf

//
// Section: .data
//

LABEL 004eae14 pNamesBlock
LABEL 004eae18 cNameEntriesCur
LABEL 004eae1c cNameEntriesMax
LABEL 004eae30 pNamesStringPool
LABEL 004eae34 cbStringPoolUsed
LABEL 004eae38 cbStringPoolTotal
LABEL 004eae3c xxxWtfNameStringPoolrelated
      
      





. , .







, CMT



, LABEL



— . . , git diff , , — , . LABEL



, CMT



, , , git diff , ( ), - , :

image

, , , , (git add --patch



).







, ( ) , , , - .







, , DVCS , №1 (BSOD ) №4 ( UDD).







№2 №3 ( ). .









, « », « », «»,  — SEH-, , , « » ( SEH- EXCEPTION_NONCONTINUABLE



).







OllyDbg ( ) — EXCEPTION_ACCESS_VIOLATION



(0xc0000005



), . , EIP , ESP/EBP , . , ( ) . , - . « » , (GetMessageTranslateMessageDispatchMessage), , . OllyDbg GUI-, , , .







, - , . EBP . , ( ) , retn



(EIP) .









, , , —  () . EXCEPTION_ACCESS_VIOLATION



, ( ). , , , , , DEP, . , ( DEP ), ( , ) , . , , , EIP , , ( , ). , — .







, , , , Markup Dumper, message loop ( ) .







( ), OllyDbg , ( , ), .







, , , EIP , . , OllyDbg , , ( ). , . . , : , , - .







, - , . , , , , , .







Findname()



Findnextname()



— API-, OllyDbg .







void DumpMarkupEx(FILE * fiOutput, int iNameType, char* pszNameType, ulong vaStart, ulong vaLimit)
{
    ulong vaCur;
    char rgchName[TEXTLEN];
    Findname(vaStart-1, iNameType, NULL);
    while(vaCur = Findnextname(rgchName) && vaCur<vaLimit)
        if(vaCur >= vaStart) fprintf(fiOutput, "%5s %.8x %s\n", pszNameType, vaCur, rgchName);
}

void DumpMarkup(FILE * fiOutput, ulong vaStart, ulong vaLimit)
{
    DumpMarkupEx(fiOutput, NM_LABEL, "LABEL", vaStart, vaLimit
    DumpMarkupEx(fiOutput, NM_COMMENT, "CMT", vaStart, vaLimit)
}
      
      





: TEXTLEN , , API- Findnextname()



rgchName



. .







, OllyDbg. , —  /, .









, , , OllyDbg. , , OllyDbg - (, OllyDbg) .







, - . , - . ( ), (unwinding) , message loop. , Markup Dumper, , , - — EIP , , — , , , , .







10—20% OllyDbg . 80—90% , OllyDbg - WinAPI-, , , . , , - NtWaitForSingleObject, . wait-, - , . Windows deadlock, . , .







, OllyDbg , . , ( New origin here EIP). New Origin Here, EIP —  WinAPI- SetThreadContext()



. , Windows , — . APC. «» APC.







, OllyDbg

, Windows, OllyDbg, , , deadlock- , , UI , , (WaitForDebugEvent



, ReadProcessMemory



, WriteProcessMemory



) — . , watchdog-, GUI- ( ) . , Spy++ , .







, , OllyDbg , . OllyDbg — , , , . , TLS , , , , , . , , , , /, .







- OllyDbg , CreateRemoteThread()



.







push param1
push param2
push param3
call <____>
int3
int3
int3
      
      





( ), , int3 — , ( ) -.







, , , OllyDbg . , . , .







, , .









, , №2 — - . , .







«» :

エキゾチックなバグ







, 0xC000026E



( 0xC000005



STATUS_ACCESS_VIOLATION



, / ), 0x004436E8



. , , 0x00400000



EXE-, - ( ).







«», , ( , ), . , 0xC000026E



. , STATUS_VOLUME_DISMOUNTED



. OllyDbg - 0x004436E8



, , , OllyDbg?







, , :







  • OllyDbg.exe . , . , OllyDbg.exe, , «Go to address» — , :

    式ダイアログに移動
  • - Ctrl+G, (, at



    CommandBar, Ctrl+G).
  • , . 0x004436E8



    — — , «Go to expression».
  • CS:EIP=001B:004436E8



    004436E8



    ( ), 004436E8



    , . , x86- , ( PE CR0 ) ( PG CR0 ).
  • () , — P (Present) PDE PTE .
  • #PF (Page Fault), .
  • Windows, (KiTrap0E()



    MmAccessFault()



    → .) — - ( ) ( , ( user-mode) VirtualAlloc



    , , - , image-backed swap-backed copy-on-write ).
  • 00443000



    , , , image-backed.
  • - (h:\soft\odbg\ollydbg.exe



    ), , , H:\



    , . , STATUS_VOLUME_DISMOUNTED



    (0xC000026E



    ).


, . , , , (working set) , , , .







画像代替 ( ), OllyDbg , - VirtualQueryEx()



, - . — , ( ) , , , , .







, ( DLL, OllyDbg) H:\



. Markup Dumper , . , (), , ( «» , ) .







, , .







, , , , , ( EIP - ) .







- , , OllyDbg (names), , , .









: . , - , . (Oleh Yuschuk), ...







, , , , , , .







Process Explorer , . , , - . Process Explorer ( VAD-), — , ReadProcessMemory()



. , .







— , «», «», . , , —  - OllyDbg OllyDbg. H:\



.







API- Insertname()



, name ( , - ) names. names , (markup), .







, names?







  • {, , }. , — . : ( O(n) ), , , , , , , , .
  • , (). , O(lb(n)) — , 30 . ( , ). , «» , .
  • , (RB, AVL, ..). , , ( ) , / , / .


, , «», . — , .







, OllyDbg OllyDbg _Insertname()



, :

アセンブラーの下のiInsertname

, , EBX, ESI, EDI, — . , — VirtualAlloc()



VirtualFree()



, memcpy



, - OllyDbg .







- : Process Monitor ( FileMon), , - ( TEST.DLL



), - TEST.UDD



, TEST.ARG



( , ). ARG- , , , OllyDbg

- ARG-.







- OllyDbg , ARG-, . : ARG- OllyDbg. ARG- custom-, , , OllyDbg — , , , VirtualAlloc()



VirtualFree()



, , , (push 4



fProtect = 4



, fProtet = PAGE_READWRITE



).







: ARG-, . . , ARG-.







like_memcpy



( memcpy()



libc) ,







Arg3 = ...
Arg2 = ...
Arg1 = ...
      
      











count = ...
src = ...
dest = ...
      
      





, , clr = 8000FF



clr = (R=255 G=0 B=128)









ARG- , OllyDbg «Custom function descriptions», .







, RTFM twice.







, - — … , .







, ? - , . () — , .







:







  • ( ), malloc()



    /HeapAlloc()



    , VirtualAlloc()



    , (, 4 ) . , EDX*24, EDX , - . , 24 — .
  • Plugin Development Kit (PDK) , Insertname() Quickinsertname() Mergequicknames(), names — API- . , , .


API- Insertname()



, :

タグとコメントの配置







!







, , . Names, , — , , , 24 , 12 , DWORD- ( — , , ). 24 12, 2 — , .







, Insertname()



:







int Insertname(ulong addr,int type,char *name)
{
    //
    //    
    //

    if(addr == NULL ||
       name == NULL ||
       type == NM_ANYNAME || type == NM_NONAME)
    {
        return -1;
    }

    //
    // ,     name- 
    //

    if(!pNamesBlock) return -1;

    if(!(cNameEntriesCur < cNameEntriesMax) && cNameEntriesMax < 1000000)
    {
        //
        //       ,   
        //

        void* const pNewBlock = VirtualAlloc(NULL, 
            2 * cNameEntriesMax * sizeof(NAME_REC), 
            MEM_COMMIT, 
            PAGE_READWRITE);

        if(pNewBlock)
        {
            //
            //   ,      
            //   .
            //

            memcpy(pNewBlock, pNameBlock, cNameEntriesMax * sizeof(NAME_REC));
            VirtualFree(pNamesBlock, 0, MEM_RELEASE);

            //
            //        , 
            //  ,    
            //     .
            //

            pNamesBlock = (NAME_REC*)pNewBlock;
            cNameEntriesMax *= 2;
        }
    }

    //      00463FB0
      
      





,

, , name



NULL, , -1



. API-:







Insertname



Inserts new or replaces existing name of given type in the name table. If name is NULL or empty, entry is deleted. Returns 0 on success and -1 on error. Note: do not call this function between calls to Quickinsertname and Mergequicknames!



int Insertname(ulong addr,int type,char *name);**



Parameters:

addr — name address;

type — name type ( NM_xxx for predefined types);

name — name to insert. If name is NULL or empty, entry is removed from the name table.

. , - OllyDbg.







. OllyDbg OllyDbg, OllyDbg , OllyDbg , {, , } c «» «» ( NM_LABEL



NM_COMMENT



).







:







DWORD Address
DWORD Value
DWORD NameType


, «Value» names, , - ASCII-. , , — - .







, , - ( ), . - .







, OllyDbg , VirtualAlloc DWORD , : , - .







, ?

Insertname()コードの続き

, : - , , , , VirtualAlloc



VirtualFree



memcpy



, , , strlen



memcpy



.







, name' , , , , , , —  , .







, :

Insertname()関数をさらに逆にします







!







, . , :







    if(!(cbStringPoolUsed + TEXTLEN < cbStringPoolTotal))
    {
        char* pNewStringPool;
        int cbDesiredNewPoolSize;

        if(GlobVarC > 4096 || cbStringPoolTotal > 320000000)
            cbDesiredNewPoolSize = cbStringPoolTotal;
        else
            cbDesiredNewPoolSize = cbStringPoolTotal * 2;

        pNewStringPool = VirtualAlloc(NULL, 
                                      cbDesiredNewPoolSize, 
                                      MEM_COMMIT,
                                      PAGE_READWRITE);
        if(pNewStringPool)
        {
            int cchUsed = 0;
            int i;
            for(int i = 0; i < cNameEntriesCur; i++)
            {
                char* pszCurString = pNamesStringPool + pNamesBlock[i].Offset;
                int   cchCurString = strlen(pszCurString) + 1;

                memcpy(pNewStringPool + cchUsed, pszCurString, cchCurString);
                pNamesBloc[i].Offset = cchUsed;
                ccUsed += cchCurString;
            }

            VirtualFree(pNamesStringPool, 0, MEM_RELEASE);

            pNamesStringPool = pNewStringPool;
            cbStringPoolUsed  = cchUsed;       
            cbStringPoolTotal = cbDesiredNewPoolSize;
            GlobalVarC = 0;
        }
    }
      
      





, (, - name', ) , (), , 320 , - ( GlobVarC



) 4096.







, memcpy



? , — ( , , ). , , , - , . , , , , 320 GlobVarC



> 4096. , GlobVarC



—  , (delayed) . , / .







OllyDbg

, , , cbStringPoolUsed + TEXTLEN < cbStringPoolTotal



,







    cchCurString = strlen(Value) + 1;
    if(!(cbStringPoolUsed + cchCurString < cbStringPoolTotal))
      
      





-, , , , 5 , 100 , , 256 ( TEXTLEN



), .







-, 256 , - . , 255 , .







, strlen(value)



, Insertname()



, 255 !







1000 , Findname()



Findnextname()



, , .







, TEXTLEN



, , . . , , , — , - , . , , , , .







, 255 ?

-, , Insertname()



. , watch expressions, , , — name-. , 255 , .







-, OllyDbg , TEXTLEN



, . , Insertname()



Quickinsertname()



, . . , , OllyScript, . , , , .







.

OllyDbg (, ).







CNFFMappedStream::Unmap



, ?Unmap@CNFFMappedStream@@UAGXEPAPAX@Z



, OllyDbg « ». . , , . :







virtual void __stdcall CNFFMappedStream::Unmap(unsigned char,void * *)
      
      





. . , , COMDAT folding.







COMDAT folding?

, . , , , , , , . , , , , , , COMDAT ( Communal Data).







« » : COMDAT, ( , , , ; , COMDAT- , , ). — COMDAT , . "ERROR"



, —  , . , , --.







:







unsigned short GetCodepointLength(const char* pCodepoint)
{
#ifdef UNICODE_STRINGS
#if UNICODE_STINGS == UTF8
    const char cp = *pCodepoint;
    unsigned short cbExtra;
    for(cbExtra = 0; (cp & 0x80) && (cbExtra < 3); cbExtra++, cp<<=1) 
        if(cp & 0x40) {if(!(cp & 0x20)) break; } else return 0;
    return 1 + cbExtra;
#else // UCS-2 or UTF-16
    return sizeof(wchar_t);
#endif
#else
    return sizeof(char);
#endif
}

LONG __stdcall CFlatArrayObject::GetDimensionsCount() // for IArrayObject::GetDimensionsCount
{
    return 1;
}

BOOL CAudioCodec::IsSampleFormatSupported(SAMPLE_FORMAT sf)
{
    return TRUE; // We support all
}
      
      





:







mov eax, 00000001
retn 4
      
      





( Microsoft ) COMDAT-folding . .







, COMDAT folding' , , « », , //



«FOLDED:



». COMDAT-folding' ( COM COM-, E_NOTIMP



— 5—6 , , , RETN



). , . , TEXTLEN



. ? OllyScript .







API- , , , , .







, «» Insertname()



, , , , ( ):

データブロックを説明するグローバル変数

PE- (EXE DLL) : ( ) swap-backed , image-backed, copy-on-write image-backed swap-backed, / / , PE-.







, ( , , OllyDbg , , , , .bss



) , OllyDbg ( ), , , swap-backed-.







H:\



( SSD-), OllyDbg.exe, , , ReadProcessMemory()



.







— , , ,  —   , . , ( ) , - , , , .











, — , , , — :







  • NAME_REC



    , {, , }. 12 . «» . .
  • , -, (, ..). «» , , . .


OllyDbg.exe



, — .

2つのデータブロック

, . , , , — , 7 ( 4 ).







, . 1.10. ! 1.10, , OllyDbg, , .







, 0x004EAE14



, , , , , OllyDbg. : — API- Insertname()



. ( , ). API- . , , . , , , , VirtualFree



, , VirtualAlloc



.







, . OllyDbg , , - (ollydbg.exe



), , - . «» , , . -, , , :







struct
{
    struct 
    {
        DWORD pNamesBlock;
        DWORD cNameEntriesCur;
        DWORD cNameEntriesMax;
    } NameBlockInfo;

    struct
    {
        DWORD pNamesStringPool;
        DWORD cbStringPoolUsed;
        DWORD cbStringPoolTotal;
        DWORD wtf;
    } StringPool;
} Metadata;

void main()
{
    HANDLE hOdbgProc;
    DWORD cbRead = 0;
    DWORD pid = ?????????;

    hOdbgProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

    ReadProcessMemory(hOdbgProc, 
        (LPCVOID)0x004EAE14, 
        &Metadata.NameBlockInfo,
        sizeof(Metadata.NameBlockInfo),
        &cbRead))

    ReadProcessMemory(hOdbgProc, 
        (LPCVOID)0x004EAE30,
        &Metadata.StringPool, 
        sizeof(Metadata.StringPool),
        &cbRead))

    VOID* pNamesBlock;
    VOID* pNamesPool;

    pNamesBlock = VirtualAlloc(0, Metadata.NameBlockInfo.cNameEntriesMax * 12, MEM_COMMIT, PAGE_READWRITE);
    pNamesPool = VirtualAlloc(0, Metadata.StringPool.cbStringPoolTotal, MEM_COMMIT, PAGE_READWRITE);

    ReadProcessMemory(hOdbgProc, 
                      (LPCVOID)Metadata.NameBlockInfo.pNamesBlock,
                      pNamesBlock,
                      Metadata.NameBlockInfo.cNameEntriesMax * 12,
                      &cbRead))

    ReadProcessMemory(hOdbgProc, 
                      (LPCVOID)Metadata.StringPool.pNamesStringPool,
                      pNamesPool,
                      Metadata.StringPool.cbStringPoolTotal,
                      &cbRead))

    DumpBlockToFile(&Metadata,  sizeof(Metadata), "names-meta.dat");
    DumpBlockToFile(pNamesBlock, Metadata.NameBlockInfo.cNameEntriesMax * 12, "names-tbl.dat");
    DumpBlockToFile(pNamesPool,  Metadata.StringPool.cbStringPoolTotal, "names-pool.dat");

    VirtualFree(pNamesBlock, 0, MEM_RELEASE);
    VirtualFree(pNamesPool,  0, MEM_RELEASE);
}
      
      





— , , ReadProcessMemory



. , - , - — , , , -, . , ( ), - — OllyDbg.







OllyDbgによるダンプ







, , OllyDbg, , - , .







- , , , , . , , , . , .







- , , , . , , , - ?







  • VirtualAlloc()



    , , (4K x86). - 0x00000FFF , .
  • , VirtualAlloc()



    Insertname()



    - , , , SYSTEM_INFO::dwAllocationGranularity, x86 64K. 16 , .
  • VirtualQueryEx()



    , () VirtualAlloc()



    , ( PAGE_READWRITE



    ), , .
  • , «» .
  • ( ) , , —  . , , 32- , 640 . , , , NM_xxxx



    , PDK.
  • ( ) - , . , - , ( ), — , (.. ). , , .
  • , , ( ).


, - , « » — , . , API- Insertname



, , .







?



, . . ?







, :







  1. , Markup Dumper, , , ( , ). , OllyDbg. , 5 , . ( ) .
  2. «» , ( , ) OllyDbg, API-, . .. Insertname()



    ( ). , UDD-.
  3. , , — OllyDbg , / . UDD-. - , . , , , .


, , . , :







typedef struct
{
    DWORD Va;      // virtual address of NAME in debugger process
    DWORD Offset;  // offset of NAME's value in string pool
    DWORD Type;    // one of NM_xxxxx values
} NAME_REC;
      
      





, for



-, cNameEntriesCur



Insertname()



, , .







P.S. . , , , , . , howto-, , , - Git VCS, - API- OllyDbg, OllyDbg, Windows . , , , , , - .








All Articles