1. 스택프레임
// ESP가 아닌, EBP레지스터를 사용하여 스택 내의 로컬 변수, 파라미터, 복귀 주소에 접근하는 기법.
왜?? ESP는 수시로 변경되기 때문에 ESP를 기준으로 프로그램을 만들면 정확한 위치를 참고할 때 CPU가 힘들어.
예시>
PUSH EBP // 함수 시작(EBP를 사용하기 전에 기존의 값을 스택에 저장)
MOV EBP, ESP // 현재 ESP(스택 포인터)를 EBP에 저장
......
......
MOV ESP, EBP // ESP를 정리 (함수 시작했을 때의 값으로 복원시킴)
POP EBP // 리턴되기 전에 저장해 놓았던 원래 EBP 값으로 복원
RETN // 함수 종료
call 02_hello.00401000 // add() 함수
PUSH EBP // EBP값을 스택에 넣어라. EBP가 메인함수에서 베이스 포인터의 역할을 하게 되니깐 EBP가 이전에 갖고 있던 값을 스택에 백업하기 위한 용도MOV EBP,ESP // ESP의 값을 EBP로 옮겨라. 즉, EBP는 ESP와 같은 값을 갖게됨.SUB ESP,8 // long은 4byte이며, a,b 2개이므로 8byte의 공간 확보MOV DWORD PTR SS:[EBP-4],1 // a의 1을 [EBP-4]에 저장.MOV DWORD PTR SS:[EBP-8],2 // b의 2를 [EBP-8]에 저장.MOV EAX,DWORD PTR SS:[EBP-8] // [EBP-8]주소에서 4byte 크기의 메모리 내용을 EAX로 이동PUSH EAX // b에 값인 2를 스택에 넣기MOV ECX,DWORD PTR SS:[EBP-4] // [EBP-4]주소에서 4byte 크기의 메모리 내용을 ECX로 이동PUSH ECX // a에 값인 1을 스택에 넣기CALL 02_hello.00401000 // add()함수ADD ESP,8PUSH EAX ; /<%d>PUSH 02_hello.004020F4 ; |format = "%d"CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printfADD ESP,8 // 스택공간 정리 (파라미터 a,b관련 공간)XOR EAX,EAX // 리턴값을 받는 EAX 초기화MOV ESP,EBP // 함수의 에필로그POP EBPRETN< CALL 02_hello.00401000 >PUSH EBP // main() 함수에서 사용되던 EBP값을 스택에 백업MOV EBP,ESP // add() 함수의 프롤로그SUB ESP,8 // 스택에 8byte의 공간확보 (로컬변수 a,b의 공간)MOV EAX,DWORD PTR SS:[EBP+8] // 파라미터 a를 가리킴MOV DWORD PTR SS:[EBP-8],EAX // a의 값인 1을 [EBP-8]에 넣음MOV ECX,DWORD PTR SS:[EBP+C] // 파라미터 b를 가리킴MOV DWORD PTR SS:[EBP-4],ECX // b의 값인 2를 [EBP-4]에 넣음MOV EAX,DWORD PTR SS:[EBP-8] // 1을 EAX에 넣음ADD EAX,DWORD PTR SS:[EBP-4] // EAX에 2를 더해서 EAX는 3이 됨MOV ESP,EBP // ESP를 원래대로 복원 (함수가 시작할때 ESP의 값을 EBP에 넣어두었다가 함수가 종료될 때 ESP를 원래대로 복원시키는 목적)POP EBP
'리버싱 > 리버싱의 핵심원리' 카테고리의 다른 글
PE구조 헤더 (0) | 2019.03.20 |
---|---|
Reversing - 스택(Stack), abex' crackme #1 분석 (0) | 2018.12.13 |
Reversing - 바이트 오더링, IA-32 Register 기본 설명 (0) | 2018.12.13 |
Reversing - Hello World! (0) | 2018.12.08 |
Reversing - 시작<기본> (0) | 2018.12.08 |