PE/COFF fájl formátum Kód visszafejtés.
Izsó Tamás
2013. december 5.
Izsó Tamás
PE/COFF – fájl formátum/ 1
Szimbólumtábla A programozási nyelvekben az típusokra, adatokra, függvényekre, ugrási címekre szimbólikus nevekkel hívatkozunk. Vannak név nélküli objektumok, amelyekhez a fordító generál szimbólikus nevet. A kód és az adat különbözo˝ memóriaterületre kerül, ezért ezek a lefordított kódban is külön szegmensben vannak. A szegmensek nevekkel rendelkeznek, ami szintén megtalálható a szimbólumtáblában. A linker számára az a szimbólum érdekes, melyek a prog˝ ˝ függ. Például globális fügvények, staram kezdocímét ol tic változók, de lényegtelenek a típusok, lokális változók, függvényparaméterek. Izsó Tamás
PE/COFF – fájl formátum/ 2
Common Object File Format COFF
˝ a Unix rendszerben a lefordíEzt a fáljformátumot elöszor tott a.out program tárolására használták. Szimbólikus nevek csak 8 karateresek lehettek. Nem támogatja a DLL-ek hívását. A fordítók által generált összes debug információ tárolása nehézségekbe ütközik. Sok módosított változata létezik, XCOFF vagy a Microsoft létrehozta a PE/COFF, linuxban viszont áttértek az ELF fájltípusra.
Izsó Tamás
PE/COFF – fájl formátum/ 3
˝ részei PE/COFF fájl fobb fájl header – milyen gépen lehet futtatni a kódot, mikor keletkezett a fájl, szimbólumok hol találhatók, stb; opcionális header – linker verzió, kód hossza, inicializált és nem inicializált adatok mérete, program elso˝ végrehajtandó utasításának a címe, stb; section header – egy bejegyzés tartalmazza a szegmens méretét és helyét, a hozzá tartozó relokációs információ helyét, line number table helyét, VM típus (read only, executable, stb); ˝ függo˝ információk; relokációs tábla – memóriahelytol line number table – forrássorok összerendelése a kóddal (debug esetén) ; szimbólumtábla – szimbólum neve (8 bájtnál hosszabb nevek esetén a string táblára hivatkozik), szimbólumot tartalmazó szegmens sorszáma, szegmensen belüli hely; String tábla – 8 karakternél hosszabb neveket tartalmazza. Izsó Tamás
PE/COFF – fájl formátum/ 4
Példa szimbólumokra — a.c int a , b; int c = 5; const i n t d = 6 4 ; char s1 [ ] = " alma " ; const char s2 [ ] = " k o r t e " ; char ∗ s3= " d i o " ; int t [100]; i n t ∗ p= t ; extern void f u n c ( const char ∗ ) ;
// // // // // // // // //
globális globális globális globális globális globális globális globális globális
, , , , , , , , ,
UNDEF s e c t i o n . data s e c t i o n . rdata . data . rdata . data UNDEF s e c t i o n . data UNDEF s e c t i o n
i n t main ( ) { i n t e=5 , f ; static int g; / / s t a t i k u s . data char s4 [ ] = " banan " ; s t a t i c char s5 [ ] = " ananasz " ; / / s t a t i k u s . data switch ( e ) { case 0 : f u n c ( " case 0 " ) ; break ; case 1 : f u n c ( s4 ) ; break ; case 2 : f u n c ( s5 ) ; goto Lab5 ; case 3 : f u n c ( s1 ) ; break ; case 4 : f u n c ( s2 ) ; break ; Lab5 : / / lokális . text case 5 : f u n c ( s3 ) ; break ; } return 0; }
Izsó Tamás
PE/COFF – fájl formátum/ 5
a.c program lefordított kódja 1. _main : 00000000 00000001 00000003 00000006 0000000D 00000012 00000015 0000001C 00000020 00000023 00000026 0000002A 0000002C 0000002F $LN6 : 00000036 0000003B 00000040 00000043 $LN5 : 00000045 00000048 00000049 0000004E 00000051 $LN4 : 00000053 00000058
55 8B 83 C7 A1 89 66 66 8B 89 83 77 8B FF
EC EC 14 45 F0 05000000 00000000 45 F4 8B 0D 04000000 89 4D F8 55 F0 55 EC 7D EC 05 63 45 EC 24 85 00000000
push mov sub mov mov mov mov mov mov mov cmp ja mov jmp
ebp ebp , esp esp , 1 4 h dword p t r [ ebp−10h ] , 5 eax , dword p t r [ $SG2485 ] dword p t r [ ebp−0Ch ] , eax cx , word p t r [ $SG2485+4 ] word p t r [ ebp−8] , cx edx , dword p t r [ ebp−10h ] dword p t r [ ebp−14h ] , edx dword p t r [ ebp−14h ] , 5 0000008F eax , dword p t r [ ebp−14h ] dword p t r $LN11 [ eax ∗ 4 ]
68 E8 83 EB
00000000 00000000 C4 04 4A
push call add jmp
o f f s e t $SG2493 _func esp , 4 0000008F
8D 51 E8 83 EB
4D F4 00000000 C4 04 3C
lea push call add jmp
ecx , [ ebp−0Ch ] ecx _func esp , 4 0000008F
68 00000000 E8 00000000
push call
o f f s e t ?s5@?1??main@@9@9 _func
Izsó Tamás
PE/COFF – fájl formátum/ 6
a.c program lefordított kódja 2. 0000005D 83 00000060 EB $LN3 : 00000062 68 00000067 E8 0000006C 83 0000006F EB $LN2 : 00000071 68 00000076 E8 0000007B 83 0000007E EB $Lab5$2496 : 00000080 8B 00000086 52 00000087 E8 0000008C 83 0000008F 33 00000091 8B 00000093 5D 00000094 C3 00000095 8D $LN11 : 00000098 00 0000009C 00 000000A0 00 000000A4 00 000000A8 00 000000AC 00
C4 04 1E
add jmp
esp , 4 $Lab5$2496
00000000 00000000 C4 04 1E
push call add jmp
o f f s e t _s1 _func esp , 4 0000008F
00000000 00000000 C4 04 0F
push call add jmp
o f f s e t _s2 _func esp , 4 0000008F
15 00000000
mov push call add xor mov pop ret lea
edx , dword p t r [ _s3 ] edx _func esp , 4 eax , eax esp , ebp ebp
00000000 C4 04 C0 E5
49 00 00 00 00 00 00 00
00 00 00 00 00 00
ecx , [ ecx ]
00 00 00 00 00 00 Izsó Tamás
PE/COFF – fájl formátum/ 7
a.obj-ban lévo˝ szimbólumtábla 000 00837809 ABS notype 001 00000001 ABS notype 002 00000000 SECT1 notype S e c t i o n length 2F , # r e l o c s 0 , checksum 0 004 00000000 SECT2 notype S e c t i o n length 7C, # r e l o c s 0 , checksum 0 006 00000000 SECT3 notype S e c t i o n length 2F , # r e l o c s 0 , checksum CFCD7EC4 008 0000000C SECT3 notype 009 00000004 UNDEF notype 00A 00000004 UNDEF notype 00B 00000190 UNDEF notype 00C 00000000 SECT3 notype 00D 00000000 SECT4 notype S e c t i o n length A, # relocs 0 , checksum 6DAF2FDC 00F 00000000 SECT4 notype 010 00000004 SECT3 notype 011 00000004 SECT4 notype 012 00000010 SECT3 notype 013 00000014 SECT3 notype 014 00000018 SECT3 notype 015 00000020 SECT3 notype 016 00000028 SECT3 notype 017 00000000 SECT5 notype S e c t i o n length B0 , # r e l o c s 0 , checksum 44157CC3 019 00000000 SECT5 notype ( ) 01A 00000080 SECT5 notype 01B 00000071 SECT5 notype 01C 00000062 SECT5 notype 01D 00000053 SECT5 notype 01E 00000045 SECT5 notype 01F 00000000 UNDEF notype ( ) 020 00000036 SECT5 notype 021 00000098 SECT5 notype
Static | @comp.id Static | @feat.00 Static | .drectve 0 , # linenums Static | .debug$S 0 , # linenums Static | .data 2 , # linenums Static | $SG2473 External | _a External | _b External | _t External | _c Static | .rdata 0 , # linenums External | _d External | _s1 External | _s2 External | _s3 External | _p Static | $SG2485 Static | ?s5@?1??main@@9@9 ( ‘ main ’ : : ‘ 2 ’ : : s5 ) Static | $SG2493 Static | .text 14 , # linenums External Label Label Label Label Label External Label Static
| | | | | | | | |
_main $Lab5$2496 $LN2 $LN3 $LN4 $LN5 _func $LN6 $LN11
Izsó Tamás
PE/COFF – fájl formátum/ 8
a.obj .text szegmenséhez tartozó relokációs tábla Offset Type A p p l i e d To Index Name −−−−−−−− −−−−−− −−−−−−−− −−−− −−−−−− 0000000E DIR32 00000000 14 $SG2485 00000018 DIR32 00000004 14 $SG2485 00000032 DIR32 00000000 21 $LN11 00000037 DIR32 00000000 16 $SG2493 0000003C REL32 00000000 1F _func 0000004A REL32 00000000 1F _func 00000054 DIR32 00000000 15 ?s5@?1??main@@9@9 ( ‘ main ’ : : ‘ 2 ’ : : s5 ) 00000059 REL32 00000000 1F _func 00000063 DIR32 00000000 10 _s1 00000068 REL32 00000000 1F _func 00000072 DIR32 00000000 11 _s2 00000077 REL32 00000000 1F _func 00000082 DIR32 00000000 12 _s3 00000088 REL32 00000000 1F _func 00000098 DIR32 00000000 20 $LN6 0000009C DIR32 00000000 1E $LN5 000000A0 DIR32 00000000 1D $LN4 000000A4 DIR32 00000000 1C $LN3 000000A8 DIR32 00000000 1B $LN2 000000AC DIR32 00000000 1A $Lab5$2496
Izsó Tamás
PE/COFF – fájl formátum/ 9
b.c fordítási egység i n t b =2; extern void f u n c ( const char ∗ s ) { int i ; f o r ( i =0; s [ i ] ; i ++ ) b+=∗s ; }
b.obj .text szegmensének a szimbólumtáblája: 000 00837809 ABS 001 00000001 ABS 002 00000000 SECT1
notype notype notype
Static Static Static
| @comp.id | @feat.00 | .drectve
004 00000000 SECT2
notype
Static
| .debug$S
006 00000000 SECT3
notype
Static
| .data
008 00000000 SECT3 009 00000000 SECT4
notype notype
E x t e r n a l | _b Static | .text
00B 00000000 SECT4
notype ( )
E x t e r n a l | _func
.text szegmenshez tartozó relokációs tábla: Offset Type A p p l i e d To Index Name −−−−−−−− −−−−−−−−−−− −−−−−−−−−−−−− −−−−−− −−−−−− 0000002B DIR32 00000000 8 _b 00000031 DIR32 00000000 8 _b Izsó Tamás
PE/COFF – fájl formátum/ 10
Szegmensek A szegmensek nevét a fordító határozza meg. A kódszegmens neve Visual C fordító esetén .text Borland fordító esetén CODE. Néhány szegmens elnevezése Visual Studió használatkor: .drective linker opció .text kódszegmens .data inicializált adatszegmens .rdata csak olvasható adatszegmens .bbs nem inicializált adatszegmens .reloc relokációs tábla .rsrc resource (ikon, cursor alak, stb. ) .edata export tábla .idata import tábla Izsó Tamás
PE/COFF – fájl formátum/ 11
Objektumok linkelése A output
.text .data
.text
.rdata
B
.text
.data
.data .rdata .rdata
C
.text .data .rdata
Izsó Tamás
PE/COFF – fájl formátum/ 12
Adatok relokálása A linker vagy loader ismeri, hogy az m modulban lévo˝ szegmens kezdete hova esik a betöltés vagy az összeszerkesztés alatt. A szimbólumtábla tartalmazza, hogy a szimbólum melyik szegmensben van. ˝ A szimbólumtábla tartalmazza, hogy a szimbólum az ot ˝ hol helyezkedik el. befoglaló szegmens kezdetétol Minden szegmensnek külön relokációs táblája van. A linker és a loader a relokációs tábla alapján tudja a címkiigazítás helyét és a relokálandó adatok méretét. A kód értelmezésével nem foglalkozik.
Izsó Tamás
PE/COFF – fájl formátum/ 13
Relokációs algoritmus foreach section s { foreach r e l o c a t i o n entry r { r e f p t r = s + r . o f f s e t ; / ∗ p t r t o r e f e r e n c e t o be r e l o c a t e d ∗ / / ∗ Relocate a PC−r e l a t i v e r e f e r e n c e ∗ / i f ( r . t y p e == REL32 ) { / ∗ r e f ’ s run−t i m e address . ∗/ r e f a d d r 1 = ADDR( s ) + r . o f f s e t + 4 ; ∗ r e f p t r = ADDR( r . symbol ) + ∗ r e f p t r − r e f a d d r ; } / ∗ Relocate an a b s o l u t e r e f e r e n c e ∗ / i f ( r . t y p e == DIR32 ) ∗ r e f p t r = ADDR( r . symbol ) + ∗ r e f p t r ; } } 1 Az IP a relokálandó operandusú utasítás végrehajtása pillanatában már a következo˝ utasításra mutat, és ehhez képest kell a relatív címet kiszámítani. A relokálás típusa egyértelmuen ˝ megadja, hogy 4-et kell a relokálás helyéhez adni. Izsó Tamás
PE/COFF – fájl formátum/ 14
Linker által használt adatok a számításokhoz ˝ A linker a program kezocímének a 0x00400000 értéket használta. Ezen a helyen a PE/COFF fájformátum header része található. A kód szegmens külön lapra kerül a virtuális memóriában. Egy lap mérete 4Kbyte, ezért az a.obj kódszegmense a 0x00401000 címre kerül. Az a.obj kódszegmense 0xB0 hosszú, ezért a b.obj kódszegmense közvetlenül az a.obj kódszegmense után, a 0x004010B0 címre kerül. A .rdata adatszegmens címtartománya: 0x00408000 0x00409A99. A .data adatszegmens új lapra, azaz a 0x0040A000 címre kerül. Izsó Tamás
PE/COFF – fájl formátum/ 15
Abszolút hivatkozás címkiszámítása Relokálandó adat az a.obj .text szegmensében: 00000037
DIR32
00000000
16
$SG2493
Relokáció helye a kódban: 00000036: 68 00000000
push
o f f s e t $SG2493
Szimbólumtábla bejegyzés: 006 00000000 SECT3 notype S t a t i c | .data length 2F , # r e l o c s 2 , # linenums 0 , chksum CFCD7EC4 016 00000028 SECT3 notype Static | $SG2493
Addr ( $SG2493 ) = Addr ( . data )+ O f f s e t ( $SG2493 ) = = 0x40A000 + 0x28 = 0x40A028 r e f p t r = Addr ( . t e x t ) + Addr ( r e l o c o f f s e t ) = 0x401000 + 0x37 = 0x401037 ∗ r e f p t r = Addr ( r . symbol ) + ∗ r e f p t r = 0x40A028 + 0 = 0x40A028
Eredmény megtekintése ollydbg alatt: 00401036
68 28A04000
PUSH OFFSET 0040A028 Izsó Tamás
PE/COFF – fájl formátum/ 16
IP relatív hivatkozás címkiszámítása Az a.obj .text szegmenséhez rendelt relokálandó adat: 00000059
REL32
00000000
1F
_func
Relokálandó kód az a.obj moduban: 00000058: E8 00000000
call
_func
A b.obj-ban lévo˝ szimbólumtábla bejegyzés: 009 00000000 SECT4 notype S t a t i c | .text length 3B , # r e l o c s 2 , # linenums 0 , chksum 14D5DB06 00B 00000000 SECT4 notype ( ) E x t e r n a l | _func
Addr ( r . symbol ) = Addr ( _func ) = Addr ( b . o b j . t e x t )+ O f f s e t ( _func ) = 0x4010B0+0 = 0x4010B0 r e f a d d r = Addr ( a . o b j . t e x t ) + r . o f f s e t + 4 = 0x401000 + 0x59 + 4 = 0x40105D r e f p t r = Addr ( . t e x t ) + r . o f f s e t = 0x401000 + 0x59 = 0x401059 ∗ r e f p t r = ADDR( r . symbol ) + ∗ r e f p t r − r e f a d d r = 0x4010B0 + 0 − 0x40105D = 0x53
Eredmény megtekintése ollydbg alatt: 00401058 E8 53000000 CALL 004010B0 Izsó Tamás
PE/COFF – fájl formátum/ 17