Reverse Engineering Basics
IA32 Basics
CPU(Central Processing Units) 의구조 ALU Register EAX s EBX ECX EDX ESI EDI ESP EBP Control Unit EIP IR Eflags I/O Unit Data Bus Address Bus
IA32 Register What is Register? 작은데이터의임시저장공간 연산처리및번지지정을도와줌 컴퓨터의장치들을제어함
IA32 Register General Purpose Register Bit Offset 31 16 8 AH AL 0 EAX (Accumulator) AX BH BL EBX (Base Register) BX CH CL ECX (Counter Register) CX DH DL EDX (Data Register) DX
IA32 Register General Purpose Register Bit Offset 31 16 0 SI DI SP BP ESI (Source Index) EDI (Destination Index) ESP (Stack Pointer) EBP (Base Pointer) Instruction Pointer Bit Offset 31 0 EIP Instruction Pointer (Program Counter)
IA32 Register Eflags Register 16 Bit 16 Bit O D I T S Z A P C Overflow Flag 16 Bit Sign Flag Carry Flag Zero Flag
IA32 Register Debug Register Bit Offset 31 DR0(Hardware Break Point Address) DR1(Hardware Break Point Address) DR2(Hardware Break Point Address) DR3(Hardware Break Point Address) DR4(Reserved) DR5(Reserved) DR6(Debug Status Register) DR7(Debug Control Register) 0 Hardware Break Point 를통해설정된주소값들이저장됨 사용되지않음 인터럽트가발생한원인에대해서알려줌 4 개의 Hardware Break Point 에대한조건을지정해줌
Reversing 을위한필수어셈블리
MOV(MOVe data) 데이터복사 Source operand의내용을 Destination operand로데이터를복사 Destination operand의내용은변하지만 Source operand의내용은변하지않음 예제.text:00401023 mov [ebp+var_c], 0Ah.text:00401027 mov eax, [ebp+var_4].text:0040102a mov ecx, eax
MOVZX(MOVe with Zero extention) Move with zero extension Source operand 를 Destination operand 로데이터를복사한후나머지비트를 0(Zero) 로채움 부호가없는정수에만사용됨 Destination operand 는반드시레지스터가되어야함 예제.text:00401011 mov ebp, esp.text:00401013 sub esp, 4.text:00401016 mov [ebp+var_4], 12FFC8h.text:0040101D movzx ebx, word ptr [ebp+var_4]
MOVZX(MOVe with Zero extention) 8 Bit Data 0 1 0 0 0 1 1 1 1 Source 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 Destination 16 Bit Register
MOVSX(MOVe with Sign extention) Move with sign extension Source operand 를 Destination operand 로데이터를복사한후나머지비트값을부호확장함 부호있는정수에만사용됨 예제.text:00401021 mov [ebp+var_4], 1200C8h.text:00401028 movsx edx, word ptr [ebp+var_4].text:0040102c movsx dx, byte ptr [ebp+var_4].text:00401031 mov esp, ebp
MOVSX(MOVe with Sign extention) Source Operand 의최상위비트를취하여복사를수행 8 Bit Data 1 0 0 0 1 1 1 1 Source 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 Destination 16 Bit Register
MOVS(MOVe String) MOVS Move data from string to string ESI(SI) 가가리키는주소에있는데이터를 EDI(DI) 가가리키는주소로복사 방향플래그 (DF) 가 1이면 ESI(SI) 와 EDI(DI) 는감소하고 0이면증가함 예제.text:00401045 sub esp, 18h.text:00401048 mov ecx, 6.text:0040104D lea esi, [ebp+var_18].text:00401050 mov edi, esp.text:00401052 rep movsd
MOVS(MOVe String) Lower Lower 7c816FD7 7c816FD7 ESI 7c940738 ESI 7c940738 FFFFFFFF FFFFFFFF EDI 7FFDE000 EDI 7c940738 41424344 41424344...... Higher Higher
ADD ADD Source operand 를동일한크기의 Destination operand 에더함 Source operand 는변하지않으며결과값은 Destination operand 에저장됨
SUB SUB Destination operand 에서 Source operand 를뺀다 Carry : 1 1 1 1 1 1 0 0 0 0 0 1 0 0 Destination operand 1 1 1 1 1 1 1 1 Source operand 0 0 0 0 0 0 1 1
MUL MUL 부호없는곱셈 AL, AX, EAX 에 8,16,32 비트연산자를곱하는명령어 연산결과는 AX, DX:AX 혹은 EDX:EAX 에저장 (operand size 에의존 ) EAX Register/m32 EDX EAX
IMUL IMUL 부호있는곱셈 곱셈부호를유지하는것이외에는 MUL 과동일함 음수부호유지를위한상위 Bit의 Set은 Overflow로취급되지않음 MOV eax, +4823424 MOV ebx, -423 IMUL ebx 499980h EAX 0FFFFFE59h EBX EDX:EAX FFFFFFFF 86635D80 음수부호유지를위해변경된값
DIV DIV 부호없는정수에대해 8, 16, 32 비트나눗셈을수행함 연산결과가저장될레지스터의크기보다큰경우 Integer Overflow 오류가발생함 DX AX AX( 몫 ) Register/m16 DX( 나머지 ) MOV dx, 0 MOV ax, 8003h MOV cx, 100h DIV cx ax = 0080h dx = 0003h
IDIV IDIV 부호있는정수에대한나눗셈을수행함 나눗셈수행전 CBW, CWD, CDQ 를통해부호비트를확장 ( 부호보존 ) idiv!start+0x8: MOV eax, -50000 00401018 99 cdq CDQ 0:000> r edx edx=7c93eb94 0:000> p cdq 수행전 MOV IDIV ebx, 256 ebx eax=ffff3cb0 ebx=7ffd3000 ecx=0012ffb0 edx=ffffffff esi=01aaf74a edi=01aaf6f2 ( 중략 ) cdq 수행후 ( 부호비트확장 ) idiv!start+0xe: 0040101e f7fb idiv eax,ebx 0:000> p eax=ffffff3c ebx=00000100 ecx=0012ffb0 edx=ffffffb0 esi=01aef74a edi=01aef6f2 eip=00401020 esp=0012ffc0 ebp=0012ffc0 iopl=0 nv up ei pl
INC INC( 증가 ) 단일 operand 에 1 을더함 0:000> p eax=00000005 ebx=7ffde000 ecx=0012ffb0 edx=7c93eb94 esi=01c6f746 edi=01c6f6f2 eip=00401018 esp=0012ffc0 ebp=0012ffc0 iopl=0 nv up ei pl cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 add!start+0x8: 00401018 40 inc eax 0:000> p eax=00000006 ebx=7ffde000 ecx=0012ffb0 edx=7c93eb94 esi=01c6f746 edi=01c6f6f2 eip=00401019 esp=0012ffc0 ebp=0012ffc0 iopl=0 nv up ei pl
DEC DEC( 감소 ) 단일 operand 에 1 을감소시킴 0:000> p eax=00000006 ebx=7ffde000 ecx=0012ffb0 edx=7c93eb94 esi=01c6f746 edi=01c6f6f2 eip=00401019 esp=0012ffc0 ebp=0012ffc0 iopl=0 nv up ei pl cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 add!start+0x9: 00401019 48 dec eax 0:000> p eax=00000005 ebx=7ffde000 ecx=0012ffb0 edx=7c93eb94 esi=01c6f746 edi=01c6f6f2 eip=0040101a esp=0012ffc0 ebp=0012ffc0 iopl=0 nv up ei pl
AND AND 두개의 Operand 에서매칭되는비트사이에부울 AND 연산수행후결과값을 Destination operand 에저장함 선택된비트를 Clear 하고나머지를유지할때사용할수있음 0 0 1 1 1 0 1 1 AND 0 0 0 0 1 1 1 1 0 0 0 0 1 0 1 1 Cleared Unchanged
OR OR 두개의 Operand 에서매칭되는비트사이에부울 OR 연산수행후결과값을 Destination operand 에저장함 선택된비트를 Set 하고다른것을유지할때사용할수있음 0 0 1 1 1 0 1 1 OR 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 Unchanged Set
XOR XOR(eXclusive OR) 두개의 Operand 에서매칭되는비트사이에부울배타적 OR 연산수행후그결과를 Destination operand 에저장함 패리티점검에사용되기도함 1 0 1 1 0 1 0 1 XOR 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 1 Odd Parity : PF = 0
SHL(SHift Left), SHR(SHift Right) Shift Left 피연산자의비트를왼쪽으로이동시키며곱셈과관련된연산 MOV dl, 10 shl dl, 2 Before After 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 5 10 Shift Right 피연산자의비트를오른쪽으로이동시키며나눗셈과관련된연산 MOV dl, 32 shr dl, 1 Before After 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 32 16
LEA(Load Effective Address) Load Effective Address 두번째 Operand 의주소를계산하고첫번째 Operand 에저장함 [ ] 연산자를제외하고대체로두번째 Operand 로 Expression 이허용안됨 Data MOV eax, edx+4 허용안됨 Data Data EDX EDX+4 MOV eax, [edx+4] 의미가달라짐 EAX LEA eax, [edx+4] LEA 사용
SCAS(SCAn String) SCAS AL/AX/EAX 에저장되어있는값과 ES:EDI 가가리키는곳에저장되어있는값을비교 (byte, word, double word) 예제.text:00401006 movzx eax, [ebp+arg_4].text:0040100a mov edi, [ebp+arg_0].text:0040100d scasb.text:0040100e jnz short loc_401017.text:00401010 mov eax, 1.text:00401015 jmp short loc_40101c.text:00401017 loc_401017: ; CODE XREF: _func+ej.text:00401017 mov eax, 0.text:0040101C loc_40101c: ; CODE XREF: _func+15j
SCAS(SCAn String) SCASB(SCAn String Byte) EDI 가가리키는곳에서 AL 과일치하는 8 비트값을찾음 EAX 00 00 00 38 7c816FD7 7c940738 EDI AL 0 0 1 1 1 0 0 0 SFP [EBP + 4] [EBP + 8]
STOS(STOre String) STOS(Store String) AL/AX/EAX 에저장되어있는값을 EDI 레지스터가가리키는곳에저장 (byte, word, double word) 예제.text:00401011 call _func.text:00401016 add esp, 4.text:00401019 lea edi, [ebp+var_4].text:0040101c stosb.text:0040101d movsx eax, byte ptr [ebp+var_4].text:00401021 push eax.text:00401022 push offset ac ; "%c\n".text:00401027 call _printf
STOS(STOre String) STOSB(STOre String Byte) AL 의내용을 EDI 가가리키는 offset 위치의메모리에저장 EAX A0 E4 9C 7D 7c816FD7 7c94077D EDI AL 0 1 1 1 1 1 1 0 SFP [EBP + 4] [EBP + 8]
REP(REPeat) REP MOVS, SCAS, STOS 등여러명령어에접두사형식으로사용되며 ECX 레지스터에저장된값만큼해당명령어를반복실행 예제.text:00401009 mov [ebp+var_4], offset azer0one@xstone.text:00401010 mov eax, [ebp+var_4].text:00401013 push eax ; char *.text:00401014 call _strlen.text:00401019 add esp, 4.text:0040101C inc eax.text:0040101d mov ecx, eax.text:0040101f mov esi, [ebp+var_4].text:00401022 lea edi, [ebp+var_24].text:00401025 rep movsb
REP(REPeat) REP MOVSD MOVSD 명령을 ECX 레지스터의값만큼반복수행 00000002h ECX 00000001h ECX 00000000h ECX ABCDEFGH ESI ABCDEFGH ABCDEFGH IJKLMNOP IJKLMNOP ESI IJKLMNOP QRSTUVW QRSTUVW QRSTUVW ESI 00000000 EDI ABCDEFGH ABCDEFGH 00000000 00000000 EDI IJKLMNOP 00000000 00000000 00000000 EDI...
Stack 개요 런타임에생성됨 프로그램실행시사용되는메모리영역중하나 Thread 단위로생성 시작위치는 Random ( 대체로비슷한위치에서시작하나, 동일함이보장되지않는다 ) Stack 의용도 임시데이터백업 지역변수저장 ( 주목적 ) 함수매개변수전달 함수호출관련정보 OS 에서필요할때사용
Four Types Of Stack Empty Stack & Full Stack top Item2 Item1 <Empty Stack> top Item2 Item1 <Full Stack> Descending Stack & Ascending Stack 0x0012FF7C Item3 0x0012FF84 Item3 0x0012FF80 Item2 0x0012FF80 Item2 0x0012FF84 Item1 0x0012FF7C Item1 <Descending Stack> <Ascending Stack>
Stack Operation TOP 4th item 4th item reg 4th item TOP 3rd item 3rd item TOP 3rd item 2nd item 2nd item 2nd item 1st item 1st item 1st item PUSH 4th items POP reg
PUSH Stack 에데이터를저장 먼저 ESP 를감소시키고 16 비트나 32 비트 Source operand 를스택에복사함 (IA32 의경우 ) ESP B ESP A A ESP Data Data Data Data Data Data Data PUSH A Data PUSH B Data Data Data Data Data Data Data
PUSH 의용도 PUSH 의용도는크게 3 가지 함수 Argument 전달 지역변수를위한공간할당 단순백업.text:00401000 _myfunc proc.text:00401000 push ebp.text:00401000 ; 여기에사용된 push는백업이목적.text:00401001 mov ebp, esp.text:00401003 push ecx.text:00401003 ; 여기에사용된 push는지역변수할당이목적 ( 중간생략 ).text:0040101b push offset adddd ; "%d %d %d %d\n".text:0040101b ; 여기에사용된 push는아규먼트전달이목적.text:00401020 call _printf
POP POP ESP 가가리키는곳에저장된내용을 Destination operand 에저장후 ESP 값증가 (IA32 의경우 ) ECX B EDX A ESP B B A ESP A A Data Data ESP Data Data Data Data Data POP ECX Data POP EDX Data Data Data Data
EIP 값을변경하는명령어 프로그램의흐름을변경할수있는명령어 JMP CALL RET
CALL 과 JMP 의차이 CALL vs JMP EIP 백업 CALL 은 EIP 값을변경하기전에스택에백업을해두지만 JMP 는백업하지않고바로변경함 CALL 을함수호출에사용 조건분기 CALL 은조건분기가능한명령어형태가존재하지않으나 JMP 는조건분기가능한명령어형태가존재 JZ, JNZ, JA, JB, JG, JL etc
RET RET 의미상 POP EIP 와동일함 (POP EIP 와같은명령은존재하지않음 ) RET POP EIP RET n 의경우 ADD ESP, n 의동작이추가된것과동일함 RET n POP EIP ADD ESP, n
LEAVE LEAVE Stack Frame 을릴리즈하는데사용하는명령어 ESP 와 EBP 를프로시저가호출될때할당된값으로복구 아래의코드와동일 MOV ESP, EBP POP EBP 리눅스용컴파일러인 gcc 에서사용
Application Binary Interface
Application Binary Interface 컴파일된코드 (binary) 와컴파일된코드, 컴파일된코드와 OS 간의인터페이스를정의 호환성유지가최대목적 OS, Architecture, Language 에따라차이점을보임 Byte Order, Data Type 별크기, Alignment 단위, Calling Convention, Object File Format, Name Decoration 등다양한주제를다룸
Endianness Multi Bytes 를저장하는순서를정의하고있음 최대 4Byte 단위로적용함 0x12345678 Little Endian Big Endian 78 56 34 12 12 34 56 78 Lower Higher Lower Higher Address Address
49 OllyDBG 환경설정
OllyDbg 다운로드
OllyDbg 다운로드 51
Windows 별설명 V I R T U A L A D D R E S S OPCODE ASSEMBLY COMMENTS INFO WINDOW REGISTERS DUMP WINDOW STACK
Plugin
Ollydbg.ini 수정
Ollydbg 를이용한 plugins 등록
Cpu option 설정
Win32API Help File 연결 Google 에서 win32api.hlp 검색후다운로드
OllyDbg 사용법 Open Restart Program Close Program Run Program Pause Execution Step Into Step Over Trace Into Trace over Execution till return Go to address Show Log Window Show Modules Window Show Memory Window Show Threads Debug할프로그램을염 debug 재시작 debug 종료 Debug 시작 Debug 일시정지한줄씩실행함수도한줄로인식하여한줄씩실행함수안으로들어가면서실행함수도한줄로인식하며실행 Return을만날때까지실행원하는주소로이동 OllyDbg를사용하여 debug한 log를보여줌현재사용하고있는모듈들을보여줌메모리를보여줌사용하고있는 thread를보여줌
OllyDbg 사용법 Show Window Show handle Show CPU Show Patchs Show Call Stacks Show BreakPoint Show References Show Trace Show source Debugging Option Appearance Option Help Window에관한정보를보여줌 Handle에과한정보를보여줌메인창으로여러정보를보여줌변화된내용을보여줌 Main Stack에관한정보를보여줌 BreakPoint에관한정보를보여줌 Reference에관한정보를보여줌 Trace실행시실행된결과를보여줌 Source에관한정보를보여줌 Debugging Option 설정 Appearance Option 설정도움말
Complied Code Pattern (Variable)
기본자료형 정수형 문자형 포인터
기본자료형 배열 64
기본자료형 구조체 65
Quiz 1. 다음내용에맞게문제를푸시오 1. 변수의개수 2. 변수별데이터 3. 변수의크기 2. 출력결과변경 2-1. 10 으로변경 2-2. C 로변경 2-3. success 출력 66
Complied Code Pattern (Control Statements)
Control statements Quiz 03-01 Success 창이뜨게변경하시오 68
Control statements Quiz 03-02 Success 창이뜨게변경하시오 코드변경없이데이터를입력하여 Success 창을띄우시오 69
Control statements Quiz 03-03 Sum 이 15 일경우출력하도록변경하시오 Sum 이 21 일경우출력결과를 i = x 형식으로 i 의값을출력하시오 70
Control statements Quiz 03-04 Message 창이출력되지않도록변경하시오 반복문안에 MessageBox 가출력되도록변경하시오 71
Quiz 1. 소스수정없이 Success 창을띄우시오 (Quiz 03-05 ~ 7) 2. 다음조건에맞게출력결과를변형하시오실행결과 n = 33670, m = 178503 으로나타나게수정하시오 (Quiz 03 08) 72
BreakPoint 활용
생성원리에따른분류 Software 디버거가직접설정 디버거가지원하는만큼설정가능 Hardware 31 DR0(Hardware Break Point Address) DR1(Hardware Break Point Address) DR2(Hardware Break Point Address) DR3(Hardware Break Point Address) DR4(Reserved) DR5(Reserved) DR6(Debug Status Register) 0 Hardware Break Point 를통해설정된주소값들이저장됨 사용되지않음 인터럽트가발생한원인에대해서알려줌 4 개의 Hardware Break Point 에대한조건을지정해줌
사용용도에다른분류 Instruction BreakPoint( 소프트웨어 ) 실행되는기계어코드위치에체크하여설정한지점이실행되기바로직전에멈춤 소프트웨어브레이크포인트 Memory BreakPoint 특정메모리읽기 / 접근명령어코드실행후멈춤
Conditional Breakpoint void main(){ int i, sum=0; for(i=0;i<=100;i++){ sum += i; } } 76
Conditional Breakpoint 조건에맞는 Breakpoint
Conditional Breakpoint 조건에맞는 Breakpoint Log 생성
Conditional breakpoint Log
Understanding Stack
Stack Frame Stack Frame 이란? 함수가사용하는 Stack 영역 실행중인함수는자신만의 Stack 영역을사용 함수실행시 Stack frame 을오픈하고함수종료시 Stack frame 을클로즈함 main() {... func1();... } func1() {... func2(); } func2() 의 stack frame func1() 의 stack frame main() 의 stack frame Call stack (call stack 은연속된 stack frame 으로구성됨 )
Frame Pointer Frame Pointer 함수의 stack frame 시작위치를가리키는레지스터 IA32에서는보통 EBP를이러한용도로사용함 Stack frame을오픈할때설정되며 stack frame이클로즈될때까지변하지않음 Frame Pointer 의필요성 Stack 내의데이터는컴파일타임에그주소를알수없음 함수실행경로에따라 call stack 의모양이변함 오늘날대부분의 OS 들은 random stack 을사용 (Stack Buffer Overflow 로인한대안이었음 ) Stack 내의데이터들은기준점 +offset 형태로컴파일되어야함 ESP 는그위치가고정되어있지않아컴파일러에게부담이큼 고정된기준점이필요함
Function Prolog & Epilog Function Prolog Stack Frame을사용하는경우함수는항상 Frame Pointer를셋업하는코드로시작 PUSH EBP ; caller의 stack frame pointer를백업 MOV EBP, ESP ; stack frame pointer 를셋업 SUB ESP, n ; 지역변수를위한공간확보 Function Epilog Stack Frame 을사용하는경우함수의끝부분에는 Frame Pointer 를원래대로복원하는코드가위치함 MOV ESP, EBP ; 지역변수공간릴리즈 POP EBP ; frame pointer 복원
함수프롤로그예제.text:0040101E _main proc near.text:0040101e.text:0040101e push ebp.text:0040101f mov ebp, esp.text:00401021 sub esp, n ( 생략 ).text:00401027 call _myfunc ----------------------------------.text:00401000 _myfunc proc near EBP myfunc() s Stack frame SFP main() s Stack frame ESP main 함수의 Stack Frame 시작점백업.text:00401000 push ebp.text:00401001 mov ebp, esp EBP SFP
함수에필로그예제.text:00401000 _myfunc proc near.text:00401000.text:00401000 push ebp.text:00401001 mov ebp, esp.text:00401003 push ecx ( 중간생략 ) EBP myfunc SFP ESP ESP.text:00401020 call _printf.text:00401025 add esp, 14h.text:00401028 mov esp, ebp.text:0040102a pop ebp.text:0040102b retn.text:0040102b _myfunc endp EBP main SFP main 함수의 Stack Frame 시작점복원
지역변수할당및해제 SUB ESP, n MOV ESP, EBP ESP ESP 할당된지역변수공간 n 해제된지역변수공간 n ESP SFP EBP ESP SFP EBP Return Return Argument Argument [ 그림 ] 지역변수공간할당 [ 그림 ] 지역변수공간해제
Frame Pointer Omission Stack Frame Pointer 를사용하지않고 ESP 를이용하여 Stack 영역에위치한데이터를참조 Stack Frame 내의데이터를 ESP+offset 형태로컴파일 함수프롤로그와에필로그생략 프로그램성능향상에도움 EBP 레지스터를다른용도로활용할수있음 프로그램성능향상에도움 대부분의컴파일러에서최적화옵션으로제공 VC++ (/O2, /FPO), GCC(--fomit-frame-pointer) 디버깅하기는어려움
스택영역에위치한데이터참조 Stack Frame 을사용하는경우 지역변수는항상 EBP N 의형태 Argument 는 EBP + N 의형태 첫번째 argument 는항상 EBP+8 에위치 Stack Frame 을사용하지않는경우 지역변수나 Argument 모두대체로 ESP + N 의형태로나타나며스택의상황에따라그값도수시로변경되어직접적인구분이어려움
지역변수와매개변수구분 Function s Local Variable Section SFP EBP- N EBP ESP Function s Local Variable Section Return Return ESP+ N Argument EBP+4+N Argument [ 그림 ] Stack Frame 을사용할때 [ 그림 ] Stack Frame 을사용하지않을때
Call Stack 식별 Stack Frame Pointer 를이용하는경우 EBP 가가리키는곳이현재실행중인함수의 stack frame 시작점 함수의 stack frame 시작점에는항상 caller 의 stack frame 시작주소가저장되어있음 Stack Frame 시작위치바로아래에는항상 return address 가저장되어있음 Stack Frame Pointer 를이용하지않는경우 Stack 내에서 return address 가저장된곳을먼저식별 Return address 윗부분은 callee 의 stack frame 영역이며아래부분은 caller 의 stack frame 영역 정확한분석을위해서는해당코드를참조하는것이필요하며, 코드가없는경우분석이매우어려움
Call Stack 조사 : ollydbg
Complied Code Pattern (Function)
Function(Caller & Callee)
Callee & Caller Saved Registers 여러함수에서공용으로사용하는레지스터의백업주체를정의하고있음 EAX ECX EDX Caller Saved Register Callee 가마음대로사용할수있는레지스터 함수호출후복귀했을때위의레지스터값이변하지않아야한다면함수호출전에 caller 는이들레지스터를백업해야함 EBX ESI EDI Callee Saved Register Caller 가마음대로사용할수있는레지스터 Callee 는이들레지스터를사용하기전에반드시백업한후사용해야하며이전함수로복귀하기전에값을복구해주어야함
Callee Saved Register Example.text:00401000 _func proc near ; CODE XREF: _main+3p.text:00401000 push ebp.text:00401001 mov ebp, esp.text:00401003 push ebx ; callee saved register이므로 backup.text:00401004 push esi.text:00401005 push edi.text:00401006 mov esi, 1.text:0040100B mov edi, 2.text:00401010 lea ebx, [esi+edi].text:00401013 pop edi ; backup된 register를원래대로복구.text:00401014 pop esi.text:00401015 pop ebx.text:00401016 pop ebp.text:00401017.text:00401017 _func retn endp
Call Function - parameter 96
Quiz 1. 04_02_02Quiz의실행결과를변조하시오 1. 첫번째 Argument가출력되게하시오 2. 복귀주소가출력되게하시오 2. 04_02_03Quiz 의실행결과를변조하시오 1. 1 개의 MessageBox 가뜨게끔호출된함수내부코드를변조하시오 97
Call Function - pointer 98
Quiz 1. 코드수정없이 Success 창이뜨게끔 Argument 를입력하시오 (04_03_02 ~ 05) 99
Call Function - structure 100
Call Function - structure 101
Quiz 1. 코드수정없이 Message 창에문자열이출력되게 Argument 를입력하시오 (04_05_02Quiz) 2. 구조체멤버의내용을변경하여 ITBANK 가출력되게변경하시오 (04_05_03Quiz) 102
Call Function - return 103
함수호출규약 Function Calling Convention 함수호출에관한규약 ( 약속 ) 아래의사항에관련된내용을규정하고있음 Argument 전달방법 Stack or Register Argument 전달순서 Leftmost to Rightmost / Rightmost to Leftmost Argument 전달에사용된 Stack 영역해제 Caller or Callee
함수호출규약비교 호출규약 매개변수전달방향 매개변수전달방법 Stack Unwinding Name Decoration stdcall R -> L Stack Callee _func@argument 크기 cdecl R -> L Stack Caller _func fastcall R -> L ECX,EDX Stack Callee @func@argument 크기 fastcall 은컴파일러마다차이점이존재함
Stack Unwinding Stack Unwinding Overview 함수호출전과후의 stack 의모양은동일해야함 지역변수공간, Saved Frame Pointer Callee 의 stack frame 에위치하며 Callee 가정리 Parameter 전달에사용된 stack 영역 Callee가사용하나, Caller의 stack frame 영역에존재 누가정리할것인가? Caller? Callee? Caller 가 Callee 로부터 return 한후정리 cdecl 가변인자지원 Callee 가 Caller 로 return 할때정리 stdcall, fastcall 코드가깔끔해짐
The C Calling Convention cdecl Argument 전달에 stack 을이용 Argument 전달순서는 rightmost to leftmost Stack unwinding 은 caller 가담당 ( ADD ESP, N 형태의커맨드이용 ) Name Decoration func -> _func
The C Calling Convention myfunc1 main() { myfunc1(1, 2, 3);... SFP Return 1 2 3 main Argument 는 R->L 순서로전달하며 Stack 을이용함.text:00401010 push 3.text:00401012 push 2.text:00401014 push 1.text:00401016 call _myfunc1.text:0040101b add esp, 0Ch Argument 를전달할때사용한 Stack 공간을 Caller(main) 가정리함 Stack
Standard Calling Convention stdcall WINAPI, CALLBACK 등 Argument 전달에 stack 을사용 Argument 전달순서는 rightmost to leftmost Stack unwinding 은 Callee 가담당 ( 일반적으로 RET N 커맨드이용 ) Name Decoration func -> _func@argument 사이즈
Standard Calling Convention myfunc1 SFP Return 1 2 3 main Argument 는 R->L 순서로전달하며 Stack 을이용함 Argument 를전달할때사용한 Stack 공간을 Callee(myfunc1) 가정리함.text:00401009 mov esp, ebp.text:0040100b pop ebp.text:0040100c retn 0Ch ------------------------------------.text:00401012 push 3.text:00401014 push 2.text:00401016 push 1.text:00401018 call _myfunc1@12 Stack
Return 값전달 Floating Point 가아닌경우 4 바이트데이터는 EAX 를통해전달 8 바이트데이터는 EDX:EAX 를통해전달 Floating Point 인경우 FPU stack 을통해전달 구조체인경우 Stack 을이용함 지역변수선언시 Return 값을저장할수있는공간을예약해둠
Calling Convention 실습 112