Portable executable file format

Bài vit này nhm mc ích i chiu thông tin t nhiu ngun khác nhau và trình bày nó theo mt ph ng pháp mà nhng ng i mi bt u có th tip cn d dàng nht.Mc dù bài vit c trình bày mt cách t m trong nhiu phn, tuy nhiên nó c nh h ng theo mc ích reverse code engineering cho nên các thông tin không cn thit s c b qua. Bn s nhn thy rng trong bài vit này tôi ã vay m n rt nhiu t các bài vit khác nhau ã c công b , ph bin và tt c các tác gi ca nhng bài vit óã c tôi nhc n vi lòng cm n sâu sc trong phn tài liu tham kho phía cui ca bài vit này. PE là nh dng file riêng ca Win32. Tt c các file có th thc thi c trên Win32 (ngoi tr các tp tin VxDs và các file Dlls 16 bit) u s dng nh dng PE. Các file Dlls 32 bit, các file COMs, các iu khin OCX , các ch ng trình ng dng nh trong Control Pannel (.CPL files) và các ng dng .NET tt c u là nh dng PE. Thm chí các ch ng trình iu khin Kernel mode ca các h iu hành NT cng s dng nh dng PE. Ti sao chúng ta li cn phi tìm hiu v nó? Có 2 lý do chính nh sau : Th nht chúng ta mun thêm các on code vào trong nhng file thc thi (ví d : k thut Keygen Injectionhoc thêm các chc nng) và th hai là thc hin công vic unpacking bng tay (manual unpacking) các file thc thi. Hu ht mi s quan tâm u dn v lý do th hai, ó là vì ngày nay hu nh các phn mm shareware nào cng u c Packedli vi mc ích là làm gim kích th c ca file ng thi cung cp thêm mt lp bo v cho file.

pdf75 trang | Chia sẻ: tlsuongmuoi | Lượt xem: 2602 | Lượt tải: 4download
Bạn đang xem trước 20 trang tài liệu Portable executable file format, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
a b ng trình compiler &l inker c a Borland và là i u áng ghi nh trong lí do s p c p sau ây. Trong m t file th c thi b Packed thì các con tr FirstThunk pointers s b làm m t hi u l c nh ng có th th nh tho ng c xây d ng l i b ng cách sao chép l i b n sao OriginalFirstThunks(which many simple packers do not seem to bother removing). ó th c s là m t i u có ích c g i là First_Thunk Rebuilder by Lunar_Dust mà s th c hi n i u này. Tuy nhiên, v i Borland khi ã t o file thì i u này là không th b i vì OriginalFirstThunks t t c u là Zero và không có INT : L i quay tr l i ví d c a chúng ta trên, tr ng Name1 field c a IMAGE_IMPORT_DESCRIPTOR u tiên ch a RVA 00 02 D5 30h (NB reverse byte order). Chuy n i giá tr này sang m t raw offset b ng cách tr i giá tr 2400h (nh ã nói trên) và chúng ta có là 2B130h. N u chúng ta quan sát trong PE file c a chúng ta chúng ta s th y tên c a DLL : 34 Ti p t c , tr ng FirstThunk field ch a RVA 00 02 D0 B4h mà sau khi convert chúng s có c Raw offset là 2ACB4h. Hãy ghi nh i u này ây là offset t i m ng c a các c u trúc DWORD-sized IMAGE_THUNK_DATA structures IAT. i u này s khi n cho bit có ý ngh a quan tr ng nh t c a nó c set (it will start with 8) và ph n th p h n s ch a s th t c a hàm c imported, ho c n u MSB không c set nó s ch a RVA khác t i tên c a hàm (IMAGE_IMPORT_BY_NAME). Trong file c a chúng ta , giá tr DWORD t i 2ACB4h là 00 02 D5 3E: ây là m t RVA khác mà khi convert sang RAW offset là 2B13E. Th i i m này nó s là m t null- terminated ASCII string. Nh chúng ta quan sát th y d i ây : Vì v y tên c a c a API u tiên c imported t kernel32.dll là DeleteCriticalSection. Có th b n ý n 2 zero bytes tr c tên c a hàm. ó là ph n t Hint element mà th ng c set là 00 00. T t c nh ng i u này có th c xác minh l i thông qua ch ng trình PE Browse Pro phân tích IAT nh hình minh h a d i ây : 35 N u nh file c loaded vào trong b nh , c dumped và ki m tra b ng ch ng trình Hex editor thì giá tr DWORD t i RVA 2D0B4h mà contained 3E D5 02 00 trên a s c overwritten b i trình loader b ng a ch c a hàm DeleteCriticalSection trong kernel32.dll : Allowing for reverse byte order this is 7C91188A. Chú ý quan tr ng : các hàm trong các DLLs h th ng luôn luôn h ng v b t u t i a ch 7XXXXXXX và cùng t i ch gi ng nhau m i khi các ch ng trình c n p. Tuy nhiên chúng hay thay i n u b n cài t l i OS c a b n và khác nhau gi a máy tính này và máy tính khác : Các a ch c ng khác nhau tùy theo t ng h i u hành, l y ví d : 36 Trình Windows Upadate c ng th nh tho ng thay i v trí c s c a các DLLs h th ng. ó là lí do t i sao m t s ng i th ng chú ý n vi c dành th i gian tìm cho c i m t breakpoint n i ti ng là point-h trên h th ng c a mình (it is prone to change unexpectedly since it is in a function inside user32.dll.) Navigating Imports in Memory Load file c a chúng ta vào trong Olly và m t l n n a hãy quan sát c a s Memory Map : Chú ý r ng a ch c a .idata section là 42D000 t ng ng v i RVA 2D000 mà chúng ta ã nói ph n tr c . Kích th c c làm tròn lên là 2000 v a khít v i memory page boundaries. C a s chính c a Olly là CPU s ch cho chúng ta th y nh ng a ch CODE section (from 401000 to 42AFFF). B n c ng có th ki m tra IAT trong c a s disassembly n u nó n m trong CODE section. Trong h u h t các tr ng h p nó s n m trong section riêng c a nó . eg : .idata nh ng b n có th xem nó trong c a s Hex-dump trong Olly b ng cách Right click vào và ch n Dump in CPU. C a s name (nh n Ctrl + N) s cho chúng ta th y c các hàm c imported: Rightclicking b t kì m t hàm nào và sau ó ch n Find References to Import s cho b n th y jump thunk stub và the instances in the code n i mà hàm ó c g i (ch có 1 trong tr ng h p c a chúng ta ): Chú ý : trong c t Comment b n s th y r ng Olly ã xác nh là hàm DeleteCriticalSection trong kernel32.dll là th c s c forwarded t i RtlDeleteCriticalSection trong ntdll.dll. (xem ph n gi i thích Export Fowarding) Ti p t c Rightclicking và ch n Follow Import in Disassembler, Olly s cho chúng ta th y a ch trong DLL thích h p n i mà code c a hàm b t u . Ví d : b t u t i 7C91188A trong ntdll.DLL: 37 N u chúng ta quan sát t i l i g i t i hàm DeleteCriticalSection t i 00401B12 chúng ta s th y nh sau: Nh các b n th y trên hình minh h a có m t l nh "CALL 00401314" nh ng Olly s thay th b ng tên c a hàm cho chúng ta. 401314 là a ch c a the jmp stub pointing to the IAT. Chú ý r ng nó là ph n c a m t b ng jmp thunk table ã c nói n ph n tr c : T i ây chúng ta l i quan sát th y có m t l nh nh y "JMP DWORD PTR DS:[0042D0B4]" ,nh ng l i m t l n n a Olly ã thay th b ng symbolic name cho chúng ta. a ch 0042D0B4 ch a c u trúc Image_Thunk_Data structure trong IAT mà ã c overwritten b i trình loader b ng a ch th c s c a hàm trong kernel32.DLL: 7C91188A. ó là nh ng gì mà chúng ta ã tìm th y thông qua vi c rightclicking and selecting Follow Import in Disassembler và c ng t dumped file ph n trên. 38 11. Adding Code to a PE File : Vi c thêm code vào m t PE file là m t i u r t c n thi t không nh ng có th crack m t protection scheme mà còn có th c ng d ng trong vi c thêm các ch c n ng vào trong PE file. Có 3 ph ng pháp chính có th add code vào trong m t file th c thì là : 1. Thêm vào m t section hi n t i khi có ch cho o n code c a b n. 2. M r ng section hi n t i khi không ch . 3. Thêm m t section m i hoàn toàn. Adding to an existing section Chúng ta c n m t section trong file mà c ánh x v i các quy n th c thi trong b nh vì v y n gi n nh t chúng ta hãy th c hành v i CODE section. Sau ó chúng ta c n m t vùng ch a toàn byte 00 (00 byte padding) trong section này. Vùng này c g i v i m t tên chung là caves có th tìm c m t cave phù h p v i nh ng gì chúng ta mong i , chúng ta s quan sát t i CODE section . Chi ti t thông qua ch ng trình LorPE : Trong hình minh h a trên chúng ta quan sát th y VirtualSize nh h n SizeOfRawData.Virtual size bi u di n s l ng code th c s . Còn kích th c c a raw data xác nh s l ng c a không gian c s d ng cho file trên a c ng c a b n. Chú ý r ng virtual size trong tr ng h p này là th p h n v i virtual size trên a c ng. ó là b i vì các trình compiler th ng làm tròn kích th c lên s p x p m t section trên m t vài ranh gi i. Trong ch ng trình Hexeditor quan sát t i phía cu i c a CODE section (phía tr c c a DATA section b t u t i 2A400h) , chúng ta có c nh sau : 39 Không gian thêm này là hoàn toàn không c s d ng và không c ánh x vào trong b nh . Chúng ta c n ph i b o m ch c ch n r ng nh ng câu l nh mà chúng ta t vào không gian này s c n p vào trong b nh . Chúng ta th c hi n i u ó b ng cách b ng cách ch nh s a thu c tính size (Size attribute). Ngay bây gi chúng ta th y là kích th c o c a Section này là 29E88, ó là b i vì t t c các trình compiler u c n.Còn i v i chúng ta chúng ta ph i c n t ng lên m t chút n a, vì v y trong LordPE ta thay i virtual size c a CODE section lên thành 29FFF , ó là kích th c l n nh t mà chúng ta có th s d ng (Toàn b Raw size ch có 2A000). th c hi n c i u này , chúng ta chu t ph i t i dòng CODE và ch n edit header, th c hi n thay i v i giá tr trên và save l i . Sau khi th c hi n xong chúng ta ã có m t không gian thích h p l u gi o n patch code c a chúng ta. i u duy nh t mà chúng ta ã thay i là VirtualSize DWORD cho CODE section trong b ng Section Table. Chúng ta c ng có th th c hi n c công vi c này b ng tay thông qua ch ng trình HexEditor. minh h a thêm n a cho công vi c này chúng ta s ti n hành thêm vào ch ng trình ví d c a chúng ta m t ch ng trình ASM nh th c hi n vi c chi m l y i u khi n c a entry point và sau ó ch tr v s th c thi cho OriginalEntryPoint. T t c công vi c này c làm thông qua Ollydbg. u tiên chúng ta ý trong LordPE thì EntryPoint là 0002ADB4 và ImageBase là 400000. Khi chúng ta load ch ng trình vào trong Olly thì EP s là 0042ADB4. Chúng ta s thêm m t s dòng sau và sau ó thay i entry point t i dòng u tiên c a o n code : MOV EAX,0042ADB4 ; Load in EAX the Original Entry Point (OEP) JMP EAX ; Jump to OEP Chúng ta s các l nh trên t i a ch 0002A300h nh chúng ta ã quan sát trên ch ng trình Hexeditor. convert RAW offset này sang m t RVA s d ng cho Olly ta s s d ng công th c sau ây (Xem thêm ph n ph l c) : RVA = raw offset - raw offset of section +virtual offset of section +ImageBase = 2A300h - 400h +1000h + 400000h = 42AF00h. 40 Sau ó ta load ch ng trình vào trong Olly và nh y t i target section c a chúng ta (nh n Ctrl + G và gõ vào giá tr ã tính toán c trên là 42AF00h). Sau khi t i v trí này, ta nh n Space, gõ vào dòng u tiên c a o n code trên sau ó nh n assemble. Ti p theo làm t ng t v i dòng code th hai. Ta có c t ng t nh hình minh h a d i ây : Ti p theo nh n chu t ph i, ch n tùy ch n Copy to Executable and All modifications.Ti p theo ch n Cpy all, m t c a s m i s xu t hi n. Trên c a s m i này ti p t c nh n chu t ph i và ch n Save File v v..Bây gi chúng ta quay tr l i v i LordPE (hay ch ng trình HexEditor) và thay i EntryPoint thành 0002AF00 (ImageBase Subtracted), ch n Save và nh n OK. Chúng ta Run ch ng trình ki m tra và reopen nó trong Olly xem New EntryPoint c a chúng ta. Trong ch ng trình HexEditor chúng ta s quan sát th y nh sau, chú ý o n c Highlight : M c dù ây ch là m t o n tiny patch , nh ng chúng ta hoàn toàn có không gian cho 386 bytes c a New code. Enlarging an Existing Section N u nh không có không gian t i phía cu i c a section .text thì chúng ta c n ph i m r ng nó. i u này a ra m t s v n nh sau : 1. N u section c followed b i các section khác thì b n s c n ph i d ch chuy n các following sections lên t o không gian. 2. Có r t nhi u các references khác nhau bên trong các file headers mà s c n ph i c i u ch nh n u b n thay i kích th c c a file. 41 3. Các References gi a các sections khác nhau ( ví d references t i data values t code section) s c n ph i c i u ch nh. V th c t là h u nh không th th c hi n c n u nh th u vi c re-compiling and re-linking file g c. H u h t các v n nêu trên u có th tránh c b ng cách n i thêm và section cu i cùng trong file exe. Nó ch ng có liên quan gì t i section ó n u nh chung ta có th thay i khi n nó phù h p v i yêu c u c a chúng ta b ng cách thay i tr ng Characteristic trong Section Table b ng tay ho c b ng LordPE. u tiên chúng ta tìm n section cu i cùng và thay i nó sao cho nó thành readable and executable. Nh chúng ta ã nói trên code section ch là ý t ng cho m t patch b i vì các characteristics flags c a nó là 60000020 , i u ó có ngh a là o n mà có th th c thi c và có th c c (executable and readable) (Xin xem thêm ph n ph l c). Tuy nhiên n u chúng ta t o n mã và d li u vào trong section này thì chúng ta s nh n c m t page fault vì nó không ph i là writeable. thay i i u này chúng ta s c n ph i thêm flag 800000000 mà s cho ta m t giá tr m i là E0000020 cho code, executable, readable and writable. T ng t nh v y n u section cu i cùng là .reloc thì flags th ng s là 42000040 cho initialized data, discardable and read-only. có th s d ng c section này chúng ta ph i thêm code, executable and writable và chúng ta ph i tr discardable m b o ch c ch n r ng trình loader s ánh x section này vào trong b nh . i u này s cho chúng ta m t giá tr m i là E0000060. Các công vi c trên có th th c hi n thành công b ng tay b ng cách thêm flags và ch nh s a l i tr ng Characteristics c a Section header thông qua ch ng trình HexEditor ho c LordPE. Trong ví d c a chúng ta thì section cu i cùng là Resources : 42 i u này s cho chúng ta m t giá tr Characteristics cu i cùng là F0000060. Nh hình minh h a trên chúng ta quan sát th y RawSize (on disk) c a section này là 8E00h bytes nh ng t t c chúng d ng nh ang c s d ng (the VirtualSize c ng gi ng h t). Bây gi chúng ta ch nh l i chúng và c ng 100h bytes vào c hai m r ng section , giá tr m i chúng ta có c là 8F00h. Có m t vài giá tr quan tr ng khác c ng c n c thay i. Tr ng SizeOfImage trong PE Header c n ph i c t ng lên b ng cách c ng thêm vào giá tr gi ng nh chúng ta ã thêm m r ng cho section ó là 100h. Do ó giá tr SizeOfImage s thay i 0003CE00h thành 0003CF00h. Có 2 tr ng khác n a mà không c th hi n trong LordPE b i vì chúng ít quan tr ng ó là : SizeOfCode và SizeOfInitialisedData trong Optional Header. ng d ng s v n th c thi mà không c n c ch nh s a nh ng có l b n nên thay i l i chúng cho tr n v n.Chúng ta s ph i thay i l i chúng b ng tay. C hai u là DWORDs t i các offset 1C và 20 t i m b t u c a PE header. (xem thêm ph n ph l c). 43 Các giá tr 0002A000 và 0000DE00 t ng ng v i các v trí xác nh nh các b n ã th y trên hình minh h a.Khi chúng ta c ng thêm 100h vào thì các giá tr này s là 0002A100 và 0000DF00.Sau ó chúng ta s o ng c th t c a cac giá tr trên thành 00 A1 02 00 và 00 00 DF 00. Cu i cùng copy và paste 100h of 00 bytes (16 hàng trong trình Hexeditor) lên phía cu i c a Section và l u l i thay i. Ch y file ki m tra các l i. Adding a New Section Trong m t vài tình hu ng b n có th c n ph i t o ra m t b n sao c a m t section ang t n t i phá v các self-checking procedures (Ví d nh SafeDisk) ho c t o ra m t section m i l u code khi các thông tin thu c quy n s h u riêng c b sung thêm vào cu i c a file (as in Delphi compiled apps). Công vi c u tiên c n làm là ph i tìm n tr ng NumberOfSections trong PE header và t ng tr ng này lên 1.Nh ã nói trong nh ng ph n tr c h u h t m i s thay i có th c th c hi n b ng ch ng trình LordPE ho c b ng tay thông qua ch ng trình HexEditor.Bây gi trong ch ng trình HexEditor c a b n hãy copy và paste 100h of 00 bytes (16 rows) lên ph n cu i c a file và ánh d u offset c a dòng m i u tiên. Trong tr ng h p c a chúng ta ó là 00038200h. ó s là n i b t u section m i c a chúng ta và s i t i tr ng RawOffset field c a Section Header.Khi chúng ta ây thì ch c ch n ó là th i i m t t t ng SizeOfImage lên 100h nh chúng ta ã làm tr c. Ti p theo chúng ta s tìm t i các section headers b t u t i offset F8 t PE header. It is not necessary for these to be terminated by a header full of zeros. S l ng các headers c a ra b i NumberOfSections và ó th ng là m t vài không gian t i phía cu i tr c khi b n thân các sections b t u.( aligned to the FileAlignment value). Tìm n section cu i cùng và thêm m t giá tr m i sau nó : Ph n ti p theo mà chúng ta ph i làm là quy t nh xem các thành ph n Virtual Offset/Virtual Size/Raw Offset and Raw Size nào c n có. có th quy t nh c i u này chúng ta xem xét các giá tr sau : Virtual offset of formerly last section (.rsrc): 34000h Virtual size of formerly last section (.rsrc): 8E00h Raw offset of formerly last section (.rsrc): 2F400h Raw size of formerly last section (.rsrc): 8E00h Section Alignment: 1000h File Alignment: 200h 44 RVA và raw offset c a section m i c a chúng ta ph i c c n ch nh v i boundaries trên.RAW Offset c a section là 00038200h nh chúng ta ã nói trên (which luckily fits with FileAlignment). có c Virtual Offset c a section c a chúng ta thì chúng ta ph i tính toán giá tr này : VirtualAddress of .rsrc + VirtualSize of .rsrc = 3CE00h. Vì SectionAlignment c a chúng ta là 1000h chúng ta ph i làm tròn giá tr này lên g n gi ng nh 1000 t c là 3D000h. Vì v y hãy i n vào header c a section c a chúng ta : The first 8 bytes will be Name1 (max. 8 chars e.g. "NEW" will be 4E 45 57 00 00 00 00 00 (byte order not reversed) The next DWORD is VirtualSize = 100h (with reverse byte order = 00 01 00 00) The next DWORD is VirtualAddress = 3D000h (with reverse byte order = 00 D0 03 00) The next DWORD is SizeOfRawData = 100h (with reverse byte order = 00 01 00 00) The next DWORD is PointerToRawData = 38200h (with reverse byte order = 00 82 03 00) The next 12 bytes can be left null The final DWORD is Characteristics = E0000060 (for code, executable, read and write as discussed above) Trong trình HexEditor chúng ta s th y nh sau : L u l i thay i , chúng s run ch ng trình và ki m tra trong LordPE : 45 12. Adding Imports to an Executable : Ph ng pháp này th ng c s d ng nhi u nh t trong tr ng h p Patching m t App khi mà chúng ta không có các hàm API mà chúng ta c n. thêm section m i, thì thông tin t i thi u nh t c yêu c u b i trình loader t o ra m t IAT h p l là : 1. M i Dll ph i c khai báo v i m t IMAGE_IMPORT_DESCRIPTOR (IID), nh k t thúc Import Directory b ng m t null-filled. 2. M i IID c n ít nh t 2 tr ng là Name1 và FirstThunk, ph n còn l i có th c set là 0(setting OriginalFirstThunk = FirstThunk i.e. duplicating the RVAs also works). 3. M i entry c a FirstThunk ph i là m t RVA t i m t Image_Thunk_Data (the IAT) mà l n l t ch a m t further RVA t i API name.Tên ph i là m t chu i null terminated ASCII c a dài có th thay i và c i tr c b i 2 bytes (hint) mà có th c thi t l p là 0. 46 4. N u các IIDs ã c thêm thì tr ng isize c a Import Table trong Data Directory có th c n ph i thay i. Các IAT entries trong Data Directory không c n ph i c ch nh s a. Vi c vi t import data m i trong m t ch ng trình HexEditor và sau ó dán vào trong target c a b n có th s t n r t nhi u th i gian.Có các công c có s n có th th c hi n c m t cách t ng quá trình này (Ví d : SnippetCreator, IIDKing, Cavewriter) nh ng vi c tìm hi u cách th c hi n công vi c này b ng tay nh th nào v n là t t h n c . Nhi m v chính là n i thêm m t IID m i lên ph n cu i c a b ng Import Table b n s c n có 20 bytes cho m i DLL c s d ng, ng quên 20 bytes dành cho null-terminator. Trong h u h t t t c các tr ng h p s không có không gian nào t i phía cu i c a Import Table hi n hành vì v y chúng ta s t o m t b n sao và xây d ng l i nó m t n i nào ó. Step 1 - create space for new a new IID Công vi c này liên quan n các b c sau ây : 1. D ch chuy n t t c các IIDs t i m t v trí mà t i ó có không gian.V trí này có th b t kì âu; phía cu i c a section .idata hi n th i ho c m t section m i hoàn toàn. 2. C p nh t RVA c a Import Directory m i trong Data Directory c a PE Header. 3. N u c n thi t, làm tròn kích th c c a section n i mà b n ã t Import Table m i vì v y m i th u c ánh x vào trong b nh (ví d : VirtualSize of the .idata section rounded up 1000h). 4. Ch y nó và n u nh nó làm vi c thì chuy n t i b c 2. N u nó không ki m tra các injected descriptors c ánh x vào trong b nh và RVA c a Import Directory là chính xác .. IMPORTANT NOTE: Các IIDs FirstThunk và OriginalFirstThunk ch a các RVAs- RELATIVE ADDRESSES có ngh a là các b n có th c t và dán Import Directory (IIDs) b t kì âu b n mu n trong PE file (taking into account the destination has to mapped into memory) và thay i RVA (và kích th c n u c n thi t) c a Import Directory trong Data Directory s khi n cho ng d ng ho t ng m t cách hoàn h o. Quay tr l i ng d ng c a chúng ta trong trình Hexeditor, IID u tiên và null terminator c tô b ng ng bao màu .Nh b n nhìn th y trong hình v d i ây không có không gian tr ng nào sau null IID: Tuy nhiên có m t s l ng không gian l n t i ph n cu i c a section .idata tr c khi section .rdata b t u. Chúng ta s copy và paste các IIDs hi n th i c a ra phía trên t i offset 2C500h t i v trí m i này : 47 convert m t offset m i thành RVA (xem thêm ph n ph l c) : VA = RawOffset - RawOffsetOfSection + VirtualOffsetOfSection = 2C500 - 2AC00 + 2D000 = 2E900h V y thay i a ch o c a import table trong Data Directory t 2D000 thành 2E900. Bây gi ch nh s a l i header c a section .idata và thay i VirtualSize b ng v i RawSize vì v y trình loader s ánh x toàn b section vào. Ch y th ng d ng c a chúng ta test. Step 2 - Add the new DLL and function details Công vi c này bao g m m t s b c sau : 1. Thêm null-terminated ASCII strings các tên c a DLL c a b n và hàm vào không gian còn tr ng trong section .idata. Tên hàm s th c s là m t c u trúc Image_Import_By_Name c preceded b i m t null DWORD. (the hint field). 2. Tính toán các RVAs c a các string trên. 3. Thêm RVA c a tên DLL vào tr ng Name1 c a IID m i c a b n. 4. Tìm DWORD sized space khác n a và t vào nó RVA c a hint/function name. Nó s tr thành Image_Thunk_Data ho c IAT c a DLL m i c a chúng ta. 5. Tính toán RVA c a Image_Thunk_Data DWORD trên và thêm nó vào tr ng FirstThunk c a IID m i c a b n. 6. Ch y ng d ng test API m i c a b n ã s n sàng c g i i n vào IDD m i c a chúng ta , chúng ta ít nh t ph i có các tr ng là Name1 và FirstThunk (các tr ng khác có th nulled). Nh chúng ta ã bi t, tr ng Name1 ch a thông tin RVA tên c a DLL trong null-terminated ASCII. Tr ng FirstThunk ch a RVA c a m t c u trúc Image_Thunk_Data mà l n l t ch a RVA khác n a c a tên hàm trong null-terminated ASCII. Tên tuy nhiên c i tr c b i 2 bytes (Hint) mà c thi t l p là zero. L y m t ví d , chúng ta mu n s d ng hàm LZCopy mà copy toàn b m t file ngu n t i m t file ích. N u file ngu n c a chúng ta c nén b ng trình ng d ng Microsoft File Compression Utility 48 (COMPRESS.EXE), thì hàm này t o ra m t file ích ã c gi i nén. N u nh file ngu n không b nén , thì hàm này s nhân ôi file g c lên. Hàm mà chúng ta nói trên n m trong file dll là lz32.dll mà hi n th i không c s d ng b i ch ng trình ng d ng c a chúng ta. Vì v y u tiên chúng ta c n ph i thêm strings cho các tên là lz32.dll và LZCopy . Trong trình Hexeditor chúng ta cu n lên trên t ch b ng import table m i c a chúng ta v phía cu i c a d li u ã t n t i tr c ó và thêm tên DLL sau ó là tên hàm lên ph n cu i này . Chú ý, các bytes null sau m i string và null DWORD tr c tên hàm : Chúng ta c n ph i tình l i các RVA c a chúng : RVA = RawOffset - RawOffsetOfSection + VirtualOffsetOfSection + ImageBase RVA of DLL name = 2C420 - 2AC00 + 2D000 = 2E820h (20 E8 02 00 in reverse) RVA of function name = 2C430 - 2AC00 + 2D000 = 2E830h (30 E8 02 00 in reverse) Giá tr u tiên có th n m trong tr ng Name1 c a IDD m i c a chúng ta nh ng giá tr th hai thì ph i n m trong m t c u trúc Image_Thunk_Data structure, v i RVA c a chúng, chúng ta sau ó có th t vào trong tr ng FirstThunk (and OriginalFirstThunk) c a IDD m i c a chúng ta.Chúng ta s t c u trúc Image_Thunk_Data structure bên d i tên hàm t i offset 2C440 và tính toán RVA mà chúng ta s t vào FirstThunk. RVA of Image_Thunk_Data = 2C440 - 2AC00 + 2D000 = 2E840 (40 E8 02 00 in reverse) N u chúng ta i n d li u trong trình HexEditor chúng ta s th y nh sau : 49 Cu i cùng chúng ta l u l i nh ng gì chúng ta ã th c hi n , ch y th ng d ng và load nó vào ch ng trình PEBrowse : 50 có th g i c hàm m i c a chúng ta , chúng ta c n ph i s d ng o n code sau : CALL DWORD PTR [XXXXXXXX] where XXXXXXXX = RVA of Image_Thunk_Data + ImageBase. Trong ví d c a chúng ta trên i v i hàm LZCopy, XXXXXXXX = 2E840 + 400000 = 42E840 vì v y chúng ta s vi t là : CALL DWORD PTR [0042E840] Chú ý cu i cùng : Dù là n u chúng ta ã thêm m t hàm c s d ng b i m t DLL mà s n sàng c dùng trong kernel32.dll , chúng ta s v n c n ph i t o ra m t IDD m i cho nó cho phép chúng ta có th t o m t IAT m i t i m t v trí thu n l i nh trên. Ph n ti p theo , ây ch là m t ph n c thêm vào trong section này. S có m t cách t ng hoàn toàn th c hi n các công vi c nh ã nói trên : 51 Chú ý , Ch ng trình SnippetCreator thêm các jump-thunks stubs c a các imports m i vào trong code c a b n trong khi v i các ch ng trình khác b n hoàn toàn ph i th c hi n i u này b ng tay . 52 13. Introduction to Packers : Trong ph n này chúng ta s m x s tác ng c a m t ch ng trình Packer n gi n i v i ng d ng c a chúng ta và c p t i 2 ph ng pháp chính c a vi c Patching m t file th c thi ã b Packed b ng cách Unpacking ho c inline-patching. Chúng ta s s d ng Packer UPX 1.25 b i vì ây th c s là m t ch ng trình nén file th c thi và không s d ng b t kì m t m t c ch b o v cao c p nào.Tác gi c a ch ng trình này là Marcus & Laszlo. u tiên chúng ta dùng PeiD Scan file c a chúng ta (file ban u ch a b Packed) : Ti p theo chúng ta s pack ng d ng c a chúng ta b ng ch ng trình UPX. ây là ch ng trính s d ng giao di n command line do ó chúng ta ph i m nó trong DOS , sau ó chúng ta gõ nh sau : "upx basecalc.exe": 53 Sau ó chúng ta hãy ý r ng kích th c ch ng trình c a chúng ta ã gi m xu ng t 225kb xu ng còn 91kb và trong PeiD chúng ta quan sát th y nh sau : S d ng ch ng trình PEBrowse Pro chúng ta quan sát th y trình Packer s thêm vào app c a chúng ta 3 sections là UPX0, UPX1 and .rsrc. Resource section bây gi ch a import directory nh ng cho m i DLL thì ch có duy nh t m t ho c 2 hàm c imported các hàm khác ã bi n m t : 54 Chú ý r ng section .rsrc ã c gi l i tên g c c a nó m c dù th m chí các ph n khác ã b thay i. Thú v n a là this dates back to a bug trong hàm LoadTypeLibEx trong oleaut32.dll in Win95 mà rsrc ã s d ng tìm ki m và n p resource section. i u này gây ra m t l i n u section b i tên. (This created an error if the section was renamed. Although this bug has been fixed it seems most packers do not rename the rsrc section for compatibility reasons) B ng vi c m ng d ng c a chúng ta trong LordPE và nh n vào Compare button chúng ta có th m b n g c c a ng d ng và quan sát s thay i c a các headers : 55 Khi chúng ta m ng d ng trong Olly , chúng ta s nh n c m t Message Box thông báo r ng file th c thi c a chúng ta ã b packed. Ch vi c nh n Ok và chúng ta s t i EntryPoint : 56 Trình Packer UPX ã nén ng d ng c a chúng ta và ã thêm the code b ng m t stub có ch a gi i thu t decompress.EntryPoint c a ng d ng ã b thay i b t u o n stub và sau ó khi stub th c hi n xong công vi c c a nó , h ng th c thi c a ch ng trình s nh y v original entrypoint (OEP) b t u ch ng trình bây gi ã c unpacked c a chúng ta. Lý do c n b n i phó v i nó là cho ch ng trình Sub decompress ng d ng c a chúng ta vào trong b nh và sau ó dump vùng nh này vào m t file có c b n sao c a ch ng trình ã c unpacked. Tuy nhiên ng d ng s không th c thi theo úng cách c a nó ó là b i vì file c dumped s có các sections riêng c a nó c aligned to memory page boundaries ch không ph i file alignment values, do ó entrypoint s v n tr t i decompression stub và Import directory rõ ràng là sai và s c n ph i ch nh s a l i. Chú ý r ng trong Olly entrypoint c a chúng ta n m t i câu l nh u tiên là PUSHAD. Câu l nh PUSHAD này là vi t t t c a PUSH ALL DOUBLE , th c hi n vi c l u t t c n i dung c a các thanh ghi 32 bit vào trong Stack , b t u t EAX cho n EDI.Theo ó Stub s th c hi n công vi c c a nó và sau ó k t thúc b ng m t câu l nh POPAD tr c l nh nh y t i OEP. POPAD sao chép l i n i dung c a các thanh ghi t Stack. i u này có ngh a là stub s ph i ph c h i l i m i th và exited without trace tr c khi th c s Run ng d ng. Vì v y ph ng pháp này là ý t ng cho nhi u packer thông d ng khác ví d nh ASPack. T th i i m c a câu l nh PUSHAD u tiên, nh ng n i dung c a Stack t i level ó ph i c hoàn toàn không c ng t i cho t i khi g p c câu l nh POPAD.N u nh chúng ta t m t Hardware breakpoint lên 4 bytes u tiên c a stack t i th i i m th c hi n l nh PUSHAD thì Olly s break t i th i i m khi mà 4 bytes này c truy c p t i câu l nh POPAD và chúng ta s t i úng câu l nh nh y t i OEP c a chúng ta. u tiên chúng ph i th c hi n câu l nh PUSHAD b ng cách nh n F7 m t l n. Ti p theo chúng ta s t m t BP c a chúng ta.Thanh ghi ESP (Stack Pointer) luôn luôn tr t i c a nh Stack do ó Right click lên ESP và ch n Follow in Dump Chúng ta s có c nh sau : Ti p theo Highlight DWORD u tiên c a Stack trong c a s Dump , chu t ph i và ch n BP>HardWare on Access>DWORD: 57 Ti p theo nh n F9 n Run ch ng trình và Olly s Break. Chúng ta quan sát s th y có l nh JMP t i OEP. OEP mà chúng ta th y ây có ImageBase là 400000h c c ng thêm vào , do ó chúng ta mu n tìm th y Real OEP thì chúng ta ph i tr i giá tr ImageBase trên. Cho nên ta có OEP là : 0002ADB4h. N u nh b n mu n gian l n ây có m t cách nhanh chóng mà luôn luôn có hi u qu v i UPX. n gi n ch là b n cu n chu t t i phía cu i c a o n code trong màn hình CPU trong Olly và phía tr c t t c ch b t u c a zero padding thì b n s th y c câu l nh POPAD nh trên. NOTE: Các Packer khác mà c ng s d ng c ch PUSHAD/POPAD có th nh y t i OEP b ng cách s d ng m t l nh PUSH y giá tr c a OEP lên trên nh c a Stack c followed b i câu câu l nh RET. CPU s ngh là ây là m t return t m t hàm call và theo thói quen thì d a ch tr v c t lên nh c a Stack. B c ti p theo chúng ta nh n F7 th c hi n l nh JMP và chúng ta s t i OEP. T i ây chúng ta s s d ng Plugin c a Olly là OllyDump Dump file này. Chu t ph i t i OEP sau ó ch n OllyDump, chúng ta s có c màn hình nh sau , th c hi n nh hình minh h a : 58 Note that OllyDump has already worked out the base address and size of image (which you could see by looking in the memory map window) and has offered to correct the entrypoint for us (although we could do this manually in the hexeditor). Nh n Dump và save file v i tên nào ó mà b n mu n (eg as basecalc_dmp.exe). Gi nguyên tr ng thái c a Olly sau khi ã th c hi n Dump. Th t không may m n khi chúng ta quan sát file c dump thì th y nó b m t icon và n u nh chúng ta c tình Run file thì chúng ta s nh n c thông báo nh sau : Chúng ta nh n c thông báo trên là b i vì h u qu c a v n alignment mà tôi ã c p trên kích th c c a file c ng ã t ng. Chúng ta m app c a chúng ta trong LordPE và quan sát t i các Sections. Các giá tr Raw offset và Raw Size ã sai. Chúng ta s ph i t o các giá tr Raw b ng v i giá tr các Virtual cho m i Section cho ng d ng c a chúng ta cho nó h at ng. Nh n chu t ph i t i UPX0 section và ch n edit header: 59 Bây gi chúng ta s làm cho RawOffset b ng VirtualAddress và RawSize b ng VirtualSize. L p l i thao tác này cho m i Sections sau ó nh n Save và Exit (this is what the "fix raw size" checkbox in OllyDump does automatically). Bây gi chúng ta quan sát th y app ã có icon nh ng khi ch y ng d ng c a chúng ta , ta s nh n c m t l i khác là : "The application failed to initialize properly". Có l i này là b i vì chúng ta ch a fix imports. Vi c Fix imports này chúng ta hoàn toàn có th th c hi n c b ng tay . Tuy nhiên s t n r t nhi u th i gian và công s c n u nh chúng ta có nhi u hàm c imported v..v. Do ó ây chúng ta s s d ng ch ng trình ImpREC 1.6F by MackT th c hi n m t cách t ng. Ch ng trình ImpREC c n ph i attach t i m t process ang ch y và c ng c n packed file tìm imports. Kh i ng ImpREC và th c hi n theo các b c sau : 1. Ch n Basecalc.exe trong danh sách Attach (it should still be running in Olly). 2. Ti p theo nh p OEP c a chúng ta là 2ADB4 vào trong textbox OEP. 3. Nh n nút IAT AutoSearch và nh n OK trên messagebox. 4. Nh n nút Get Imports . 5. Nh n Show Invalid trong tr ng h p c a chúng ta không có invalid nào. 6. Nh n Fix Dump và ch n file mà chúng ta ã dump là basecalc_dmp.exe. 7. Okie ..Thoát kh i ImpREC. 60 Ch ng trình ImpREC s l u file ã fix v i tên nh sau : basecalc_dmp_.exe. Chúng ta ch y th file này ki m tra. N u nh chúng ta phân tích file này chúng ta s th y kích th c c a nó ã t ng lên và có thêm m t section n a có tên là mackt ó là n i mà ImpREC a import data m i : Vì UPX ch là m t ch ng trình nén, nó n gi n ch là l y existing import data và l u nó l i trong resource section mà không encrypting or damaging it. ó là lý do t i sao ImpREC có th tìm c t t c các vaild imports mà không c n ph i resorting to tracing or rebuilding nó ch l y import directory t file th c thi ã b packed trong b nh và transfer nó t i section m i trong file th c thi ã c unpacked. Gi chúng ta hãy Scan file ã c unpacked trong PEID xem : 61 Trên ây ch là ph n minh h a các b c c n thi t cho vi c th c hi n unpack m t file th c thi ã b packed b ng m t packer n gi n. Tuy nhiên có r t nhi u các packers cao c p mà các packer này thêm r t nhi u các c ch b o v khác nhau ví d nh : antidebugging và anti-tampering tricks, encryption of code và IAT, stolen bytes, API redirection, etc mà trong ph m vi c a bài vi t này tôi không th c p h t c, mong các b n b quá cho . Trong m t s tr ng h p n u nh c n thi t chúng ta ph i Patch m t file ã b packed , i u này giúp chúng ta có th tránh c vi c không c n ph i unpacking file thì có m t k thu t c s d ng ó là inline patching . Nó liên quan n vi c patching code t i th i i m runtime trong b nh sau khi quá trình decompression stub ã hoàn thành xong công vi c c a mình và cu i cùng nh y t i OEP th c thi ng d ng. Nói cách khác ,chúng ta i cho n khi ng d ng c a chúng ta ã c unpacked trong b nh , thì nh y t i patching code mà chúng ta ã injected, cu i cùng sau ó nh y tr v OEP. minh h a cho k thu t này chúng ta s inject code vào trong file th c thi ã b packed c a chúng ta b n ra m t thông báo và cho chúng ta bi t khi ng d ng ã c unpacked trong b nh . Sau ó khi chúng ta nh n OK thì s nh y t i OEP và ng d ng s th c thi m t cách bình th ng. Nhi m v u tiên là chúng ta ph i tìm ki m m t n i cho o n code c a chúng ta vì v y hãy m packed app vào trong trình Hexeditor và tìm ki m m t kho ng không gian phù h p còn g i là suitable "cave". Kho ng không gian tr ng này n m t i phía cu i c a section là t t h n c b i vì nó ít c s d ng b i packer và có th m r ng c b ng cách n i r ng section n u th y c n thi t (Xin xem l i ph n adding code to a PE file.) B n có th quan sát th y hi u qu c a Packer UPX kho ng không gian chúng ta c n là r t khó tuy nhiên v n có m t kho ng nh (small cave) t n t i ây.Bây gi chúng ta thêm "Unpacked..." và "Now back to OEP" trong ASCII column c a ch ng trình HexEditor. T ng t nh hình minh h a d i ây : 62 i u này s ánh d u d u v t c a chúng ta patch trong Olly mà không c n ph i lo l ng v vi c tính toán các VAs. L u l i nh ng thay i và m ng d ng c a chúng ta trong Olly. Chu t ph i t i c a s Hex window và ch n search for binary string. Bây gi nh p vào là "Unpacked" và ý t i VA c a 2 strings. Trong c a s CPU Window, nh n chu t ph i và ch n Goto expression. Nh p a ch c a string u tiên và b n s quan sát 2 strings trong hexadecimal form. Olly ã không analysed nó m t cách úng n do ó nó hi n th không ra thành m t o n code không có ý ngh a gì. Highlight o n code (the next free row underneath) và nh n Space Bar assemble the following instructions : PUSH 0 PUSH 440C30 [address of first string] PUSH 440C40 [address of second string] PUSH 0 CALL MessageBoxA JMP 42ADB4 Make a note of the address of our first PUSH instruction - 440C4E. o n code c a chúng ta s trông nh sau trong Olly : Ti p theo chu t ph i và ch n copy to executable, selection. Trong c a s m i xu t hi n , rightclick và ch n save file etc. If we check in the hexeditor we see our code has been added: 63 Cu i cùng chúng ta c n ph i thay i l nh JMP t i phía cu i c a UPX stub nh y t i o n code c a chúng ta. Tìm l nh nh y này nh ã c p ph n trên, doubleclick vào JMP instruction assemble và thay i address thành 440C4E. L u l i thay i m t l n n a và run app c a chúng ta test : Clicking OK resumes BaseCalc.!!!!!!!!!!!!! 14. References & Further Reading : The Portable Executable Format -- Micheal J. O'Leary The Portable Executable File Format from Top to Bottom -- Randy Kath Peering Inside the PE: A Tour of the Win32 Portable Executable File Format -- Matt Pietrek An In-Depth Look into the Win32 Portable Executable File Format (2 parts)-- Matt Pietrek Windows 95 Programming Secrets -- Matt Pietrek Linkers and Loaders -- John R Levine Secrets of Reverse Engineering -- Eldad Eilam PE.TXT -- Bernd Luevelsmeyer Converting virtual offsets to raw offsets and vice versa -- Rheingold PE Tutorial -- Iczelion The Portable Executable File Format -- KGL PE Notes, Understanding Imports -- yAtEs Win32 Programmer's Reference What Goes On Inside Windows 2000: Solving the Mysteries of the Loader -- Russ Osterlund Tool Interface Standard (TIS) Formats Specification for Windows Adding Imports by Hand -- Eduardo Labir (Havok), CBJ Enhancing functionality of programs by adding extra code -- c0v3rt+ Working Manually with Import Tables -- Ricardo Narvaja All tutorials concerning manual unpacking (especially those from ARTeam, with special reference to the Beginner Olly series by Shub and Gabri3l. 64 15. Complete PE Offset Reference : The DOS Header : OFFSET SIZE NAME EXPLANATION 00 WORD e_magic Magic DOS signature MZ (4Dh 5Ah) 02 WORD e_cblp Bytes on last page of file 04 WORD e_cp Pages in file 06 WORD e_crlc Relocations 08 WORD e_cparhdr Size of header in paragraphs 0A WORD e_minalloc Minimum extra paragraphs needed 0C WORD e_maxalloc Maximum extra paragraphs needed 0E WORD e_ss Initial (relative) SS value 10 WORD e_sp Initial SP value 12 WORD e_csum Checksum 14 WORD e_ip Initial IP value 16 WORD e_cs Initial (relative) CS value 18 WORD e_lfarlc File address of relocation table 1A WORD e_ovno Overlay number 1C WORD e_res[4] Reserved words 24 WORD e_oemid OEM identifier (for e_oeminfo) 26 WORD e_oeminfo OEM information; e_oemid specific 28 WORD e_res2[10] Reserved words 3C DWORD e_lfanew Offset to start of PE header The PE Header : 00 DWORD Signature PE Signature PE.. (50h 45h 00h 00h) 04 WORD Machine 014Ch = Intel 386, 014Dh = Intel 486, 014Eh = Intel 586, 0200h = Intel 64-bit, 0162h=MIPS 06 WORD NumberOfSections Number Of Sections 08 DWORD TimeDateStamp Date & time image was created by the linker 65 0C DWORD PointerToSymbolTable Zero or offset of COFF symbol table in older files 10 DWORD NumberOfSymbols Number of symbols in COFF symbol table 14 WORD SizeOfOptionalHeader Size of optional header in bytes (224 in 32bit exe) 16 WORD Characteristics see below 18 ********** START OF OPTIONAL HEADER ************************************** 18 WORD Magic 010Bh=32-bit executable image 020Bh=64-bit executable image 0107h=ROM image 1A BYTE MajorLinkerVersion Major version number of the linker 1B BYTE MinorLinkerVersion Minor version number of the linker 1C DWORD SizeOfCode size of code section or sum if multiple code sections 20 DWORD SizeOfInitializedData as above 24 DWORD SizeOfUninitializedData as above 28 DWORD AddressOfEntryPoint Start of code execution, optional for DLLs, zero when none present 2C DWORD BaseOfCode RVA of first byte of code when loaded into RAM 30 DWORD BaseOfData RVA of first byte of data when loaded into RAM 34 DWORD ImageBase Preferred load address 38 DWORD SectionAlignment Alignment of sections when loaded in RAM 3C DWORD FileAlignment Alignment of sections in file on disk 40 WORD MajorOperatingSystemVersion Major version no. of required operating system 42 WORD MinorOperatingSystemVersion Minor version no. of required operating system 44 WORD MajorImageVersion Major version number of the image 46 WORD MinorImageVersion Minor version number of the image 48 WORD MajorSubsystemVersion Major version number of the subsystem 4A WORD MinorSubsystemVersion Minor version number of the subsystem 4C DWORD Reserved1 66 50 DWORD SizeOfImage Amount of memory allocated by loader for image. Must be a multiple of SectionAlignment 54 DWORD SizeOfHeaders Offset of first section, multiple of FileAlignment 58 DWORD CheckSum Image checksum (only required for kernel-mode drivers and some system DLLs). 5C WORD Subsystem 0002h=Windows GUI, 0003h=console 5E WORD DllCharacteristics 0001h=per-process library initialization 0002h=per-process library termination 0003h=per-thread library initialization 0004h=per-thread library termination 60 DWORD SizeOfStackReserve Number of bytes reserved for the stack 64 DWORD SizeOfStackCommit Number of bytes actually used for the stack 68 DWORD SizeOfHeapReserve Number of bytes to reserve for the local heap 6C DWORD SizeOfHeapCommit Number of bytes actually used for local heap 70 DWORD LoaderFlags This member is obsolete. 74 DWORD NumberOfRvaAndSizes Number of directory entries. 78 ********** START OF DATA DIRECTORY ************************************** 78 DWORD IMAGE_DATA_DIRECTORY0 RVA of Export Directory 7C DWORD size of Export Directory 80 DWORD IMAGE_DATA_DIRECTORY1 RVA of Import Directory (array of IIDs) 84 DWORD size of Import Directory (array of IIDs) 88 DWORD IMAGE_DATA_DIRECTORY2 RVA of Resource Directory 8C DWORD size of Resource Directory 90 DWORD IMAGE_DATA_DIRECTORY3 RVA of Exception Directory 94 DWORD size of Exception Directory 98 DWORD IMAGE_DATA_DIRECTORY4 Raw Offset of Security Directory 9C DWORD size of Security Directory A0 DWORD IMAGE_DATA_DIRECTORY5 RVA of Base Relocation Directory 67 A4 DWORD size of Base Relocation Directory A8 DWORD IMAGE_DATA_DIRECTORY6 RVA of Debug Directory AC DWORD size of Debug Directory B0 DWORD IMAGE_DATA_DIRECTORY7 RVA of Copyright Note B4 DWORD size of Copyright Note B8 DWORD IMAGE_DATA_DIRECTORY8 RVA to be used as Global Pointer (IA-64 only) BC DWORD Not used C0 DWORD IMAGE_DATA_DIRECTORY9 RVA of Thread Local Storage Directory C4 DWORD size of Thread Local Storage Directory C8 DWORD IMAGE_DATA_DIRECTORY10 RVA of Load Configuration Directory CC DWORD size of Load Configuration Directory D0 DWORD IMAGE_DATA_DIRECTORY11 RVA of Bound Import Directory D4 DWORD size of Bound Import Directory D8 DWORD IMAGE_DATA_DIRECTORY12 RVA of first Import Address Table DC DWORD total size of all Import Address Tables E0 DWORD IMAGE_DATA_DIRECTORY13 RVA of Delay Import Directory E4 DWORD size of Delay Import Directory E8 DWORD IMAGE_DATA_DIRECTORY14 RVA of COM Header (top level info & metadata... EC DWORD size of COM Header ...in .NET executables) F0 DWORD ZERO (Reserved) Reserved F4 DWORD ZERO (Reserved) Reserved F8 ********** START OF SECTION TABLE *******Offsets shown from here******** 00 8 Bytes Name1 Name of first section header 08 DWORD misc (VirtualSize) Actual size of data in section 68 0C DWORD virtual address RVA where section begins in memory 10 DWORD SizeOfRawData Size of data on disk (multiple of FileAlignment) 14 DWORD pointerToRawData Raw offset of section on disk 18 DWORD pointerToRelocations Start of relocation entries for section, zero if none 1C DWORD PointerToLinenumbers Start of line-no. entries for section, zero if none 20 WORD NumberOfRelocations This value is zero for executable images. 22 WORD NumberOfLineNumbers Number of line-number entries for section. 24 DWORD Characteristics see end of page below 00 8 Bytes Name1 Name of second section header ********** Repeats for rest of sections ************************************** The Export Table : OFFSET SIZE NAME EXPLANATION 00 DWORD Characteristics Set to zero (currently none defined) 04 DWORD TimeDateStamp often set to zero 08 WORD MajorVersion user-defined version number, otherwise zero 0A WORD MinorVersion as above 0C DWORD Name RVA of DLL name in null-terminated ASCII 10 DWORD Base First valid exported ordinal, normally=1 14 DWORD NumberOfFunctions Number of entries in EAT 18 DWORD NumberOfNames Number of entries in ENT 1C DWORD AddressOfFunctions RVA of EAT (export address table) 20 DWORD AddressOfNames RVA of ENT (export name table) 24 DWORD AddressOfNameOrdinals RVA of EOT (export ordinal table) The Import Table : OFFSET SIZE NAME EXPLANATION 00 DWORD OriginalFirstThunk RVA to Image_Thunk_Data 04 DWORD TimeDateStamp zero unless bound against imported DLL 08 DWORD ForwarderChain pointer to 1st redirected function (or 0) 0C DWORD Name1 RVA to name in null-terminated ASCII 10 DWORD FirstThunk RVA to Image_Thunk_Data 69 Image Characteristics Flags : FLAG EXPLANATION 0001 Relocation info stripped from file 0002 File is executable (no unresolved external references) 0004 Line numbers stripped from file 0008 Local symbols stripped from file 0010 Lets OS aggressively trim working set 0020 App can handle >2Gb addresses 0080 Low bytes of machine word are reversed 0100 requires 32-bit WORD machine 0200 Debugging info stripped from file into .DBG file 0400 If image is on removable media, copy and run from swap file 0800 If image is on a network, copy and run from swap file 1000 System file 2000 File is a DLL 4000 File should only be run on a single-processor machine 8000 High bytes of machine word are reversed Section Characteristics Flags : FLAG EXPLANATION 00000008 Section should not be padded to next boundary 00000020 Section contains code 00000040 Section contains initialised data (which will become initialised with real values before the file is launched) 00000080 Section contains uninitialised data (which will be initialised as 00 byte values before launch) 00000200 Section contains comments for the linker 00000800 Section contents will not become part of image 00001000 Section contents comdat (Common Block Data) 00008000 Section contents cannot be accessed relative to GP 00100000 to 00800000 Boundary alignment settings 01000000 Section contains extended relocations 02000000 Section can be discarded (e.g. .reloc) 04000000 Section is not cacheable 08000000 Section is pageable 10000000 Section is shareable 20000000 Section is executable 40000000 Section is readable 70 80000000 Section is writable 16. Relative Virtual Addressing Explained : Trong m t file th c thi hay m t file DLL, thì RVA luôn luôn là a ch c a m t item khi c n p vào trong b nh , v i base address (ImageBase) c a imaging file c tr i : RVA = VA ImageBase do dó VA = RVA + ImageBase. It's exactly the same thing as file offset but it's relative to a point in virtual address space, not the beginning of the PE file. Ví d :N u m t PE file n p t i a ch 400000h trong virtual address (VA) space và ch ng trình b t u th c thi t i virtual address 401000h, chúng ta có th nói r ng ch ng trình b t u th c thi t i RVA 1000h. An VA is relative to the starting VA of the module. The RVA of an item will almost always differ from its position within the file on disk - the offset. This is a pitfall for newcomers to PE programming. Most of the addresses in the PE file are RVAs and are meaningful only when the PE file is loaded into memory by the PE loader Thu t ng "Virtual Address" c s d ng b i vì Windows t o ra m t không gian a ch o riêng bi t cho m i process, không l thu c vào physical memory. Cho h u h t t t c các m c ích , m t virtual address c xem xét ch là m t address. Nh nói trên, m t virtual address là không th d oán tr c c nh m t RVA, b i vì trình loader không th load the image at its preferred base address. T i sao PE file format l i s d ng RVA? ó là làm gi m b t quá trình n p c a trình loader. ó là b i vì n u m t module có th c relocated b t kì v trí nào trong không gian a ch o , nó s gây tr ng i cho trình loader fix m i hardcoded address trong module. Nh ng ng c l i , n u t t c relocatable items trong file use RVA, there is no need for the loader to fix anything: nó ch n gi n relocates toàn b moduel t i m t new starting VA. Converting virtual offsets to raw offsets and vice versa (from Rheingold) Chuy n i các raw offsets (the one in a file you see in a HexEditor) thành virtual offsets (the one you see in a debugger) là c c k h u ích n u nh b n làm vi c v i PE Header. Chính vì lý do này b n c n ph i bi t m t vài giá tr t PE Header. B n c n ph i bi t ImageBase, the name of the section in which your offset lies. D i ây b n s xem m t ví d c a m t PE Header t i m b t u c a file (where it is actually a MZ header until offset 80h) cho t i ph n cu i nh ngh a các sections (offset 23Fh). Ví d này c minh h a b ng ch ng trình notepad.exe. 71 Ví d 1 - Converting raw offset 7800h to a virtual offset: ImageBase (DWORD value 34h bytes after the PE header begins, in our case B4h) là 40000h. The Section Table starts F8h bytes after the PE header starts, in our case 178h. It is this part: The colored values tell us the following values : 72 The Virtual Size và các giá tr c ánh màu da cam trong output c a trình Hexeditor trên là không quan tr ng i v i quá trình chuy n i nh ng s có nh ng ch c n ng khác(see Section Table page). Chúng ta mu n convert raw offset 7800h. i u này d ng nh là rõ ràng b i offset này n m trong .rsrc section b i vì .rsrc b t u t i 7000h (Raw Offset) và 6000h bytes long (Raw Size). Offset 7800h is located 800h bytes sau ch b t u c a section trong file. Vì t t c các sections ã c copy vào trong memory just like they are in the file, this address will be found 800h bytes after the section starts in memory (7000h; Virtual Offset). The offset we search is at 7800h. This is absolutely not common that the raw offset equals the virtual offset (without ImageBase). In this case it is only because the sections start at the same offset in memory and in the file. Công th c chung là : RVA = RawOffset_YouHave - RawOffsetOfSection + VirtualOffsetOfSection + ImageBase (ImageBase = DWORD value 34h bytes after the PE header begins) The conversion from a virtual offset to a raw offset just goes the other way round. The general formula is: Raw Offset = RVA_YouHave - ImageBase - VirtualOffsetOfSection + RawOffsetOfSection For 40A000 that is: 40A000-400000-7000+7000 = A000 There are also automated tools to perform the above conversions. Pressing the "FLC" button on the PE Trình Editor c a LordPE s cho phép chúng ta convert an RVA to an offset: Ch ng trình Offset Calculator c ng cho phép m t conversion one-way from RVA to Raw Offset. 73 Ch ng trình RVA Calculator cho phép onversion both ways: ..::[The End]::.. 03/08/2005 --++--==[ Greatz Thanks To ]==--++-- - Thank to my family, Computer_Angel, Moonbaby , Zombie_Deathman, Littleboy, Benina, QHQCrker, the_Lighthouse, Hoadongnoi, Nini ... all REA s members, HacNho,RongChauA,Deux, tlandn, dqtln , ARTEAM (especially Goppit) .... all my friend, and YOU. --++--==[ Special Thanks To ]==--++-- - coruso_trac, patmsvn, trm_tr v..v.. and all brothers in VSEC 74 >>>> If you have any suggestions, comments or corrections email me: kienbigmummy[at]gmail.com

Các file đính kèm theo tài liệu này:

  • pdfPortable Executable File Format.pdf
Tài liệu liên quan