Jika Anda menggunakan OllyDbg bukan untuk men -debug aplikasi Anda sendiri yang informasinya telah Anda debug, tetapi untuk rekayasa balik atau penelitian pihak ketiga, aktivitas khas Anda adalah menyelidiki kode mesin produk orang lain, memahami esensi dari apa yang terjadi dan menempatkan sejumlah besar label (label ) dan komentar di seluruh kode, serta bagian data. Anda secara sistematis mengeksplorasi esensi prosedur / fungsi dan variabel dan memberinya nama yang mencerminkan pemahaman Anda tentang tujuannya.
Dan sekarang, setelah beberapa jam (atau bahkan berhari-hari) bekerja, ketika Anda mengetahui dan menandatangani ratusan, atau bahkan ribuan prosedur dan variabel, OllyDbgtiba-tiba macet atau macet, menghilangkan semua pekerjaan Anda (yang mungkin menyertakan tidak hanya label dan komentar dalam jumlah besar, tetapi juga breakpoint dan modifikasi yang ditempatkan di tempat yang tepat). Ini hanya membuang-buang waktu dan merupakan faktor yang sangat mendemotivasi, yang darinya seseorang menyerah dan menjadi pucat.
Artikel ini adalah tentang bagaimana saya menggunakan OllyDbg dalam keadaan darurat untuk dengan cepat merekayasa balik OllyDbg (sebagian), menyimpan data yang tergantung pada seutas benang dan mengembangkan resep untuk tindakan jika terjadi bencana seperti itu.
Karena Anda terus membaca artikel ini, mari kita sepakati beberapa hal dari awal:
- OllyDbg 1.xx, OllyDbg 2.xx, , - , 1.xx ( ).
- OllyDbg , , , .. « » — « », , , , OllyDbg. , , — .
- IDA Pro , OllyDbg . Audi « BMW» . — , .
- , . « » . howto- , SSH, , , , ? , « BSOD» — , , . ?
«» , , , , , . :
- (Labels) — OllyDbg , , .
- (Comments) — .
- (Breakpoints) — .
- (Hints) — OllyDbg, , 4 4 , DWORD.
, , , . , , . , , , — - .
, , , , { → } OllyDbg names. .
- NM_LABEL — User-defined label
- NM_EXPORT — Exported (global) name
- NM_IMPORT — Imported name
- NM_LIBRARY — Name extracted from library, object file or debug data
- NM_CONST — User-defined constant (currently not implemented)
- NM_COMMENT — User-defined comment
- NM_LIBCOMM — Automatically generated comment from library or object file
- NM_BREAK — Condition related with breakpoint
- NM_ARG — Arguments decoded by analyser
- NM_ANALYSE — Comment added by analyser
- NM_BREAKEXPR — Expression related with breakpoint
- NM_BREAKEXPL — Explanation related with breakpoint
- 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 :
- — . BSOD . .
- — . , , , , « » « ». ( ?), . . , OllyDbg, , - , .
- . OllyDbg . , OllyDbg.exe, . : , OllyDbg «» 27 . , . , OllyDbg, deadlock - Windows, - ( - ). , Microsoft- Spy++, « » , Spy++ GUI- DLL, . - , GUI-. , , . .
- OllyDbg UDD-, . UDD- , OllyDbg . , . OllyDbg , , — , , UDD-, . , - . , OllyDbg UDD, UDD-. , UDD- , , , , . — DLL. OllyDbg «» UDD-, , UDD-, , UDD-. UDD-.
, , , , , , , (.. — ).
UDD — . , , . , . .
UDD :
- . , git ( ) ( , ). diff , (, custom diff git). , merge — .
- , , . , UDD .
- , . - , , . - ( — , , , , , , ..) - - .
- VCS Git , . : ( WinMain()
), — ( , ). , , . , ( memcpy
, strncat
, qsort
). , , (merge conflict), , . « », .
, - - , , , « », , « », . , , - , , ( , new
).
, - ( ) , , , , .
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 , ( ), - , :
, , , , (git add --patch
).
, ( ) , , , - .
, , DVCS , №1 (BSOD ) №4 ( UDD).
№2 №3 ( ). .
, « », « », «», — SEH-, , , « » ( SEH- EXCEPTION_NONCONTINUABLE
).
OllyDbg ( ) — EXCEPTION_ACCESS_VIOLATION
(0xc0000005
), . , EIP , ESP/EBP , . , ( ) . , - . « » , (GetMessage→TranslateMessage→DispatchMessage), , . 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.
, 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?
- {, , }. , — . : ( ), , , , , , , , .
- , (). , — , 30 . ( , ). , «» , .
- , (RB, AVL, ..). , , ( ) , / , / .
, , «», . — , .
, OllyDbg OllyDbg _Insertname()
, :
, , 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 , : , - .
, ?
, : - , , , , VirtualAlloc
VirtualFree
memcpy
, , , strlen
memcpy
.
, name' , , , , , , — , .
, :


, . , :
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) . , / .
, , , 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
, , . . , , , — , - , . , , , , .
-, , Insertname()
. , watch expressions, , , — name-. , 255 , .
-, OllyDbg , TEXTLEN
, . , Insertname()
Quickinsertname()
, . . , , OllyScript, . , , , .
CNFFMappedStream::Unmap
, ?Unmap@CNFFMappedStream@@UAGXEPAPAX@Z
, OllyDbg « ». . , , . :
virtual void __stdcall CNFFMappedStream::Unmap(unsigned char,void * *)
. . , , 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
, — .
, . , , , — , 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, , - , .
- , , , , . , , , . , .
- , , , . , , , - ?
-
VirtualAlloc()
, , (4K x86). - 0x00000FFF , . - ,
VirtualAlloc()
Insertname()
- , , , SYSTEM_INFO::dwAllocationGranularity, x86 64K. 16 , . -
VirtualQueryEx()
, ()VirtualAlloc()
, (PAGE_READWRITE
), , . - , «» .
- ( ) , , — . , , 32- , 640 . , , ,
NM_xxxx
, PDK. - ( ) - , . , -
, ( ), — , (.. ). , , . - , , ( ).
, - , « » — , . , API- Insertname
, , .
?
, . . ?
, :
- , Markup Dumper, , , ( , ). , OllyDbg. , 5 , . ( ) .
- «» , ( , ) OllyDbg, API-, . ..
Insertname()
( ). , UDD-. - , , — 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 . , , , , , - .