Stack (스택)
• Stack(스택)
- 메모리의 한 부분으로 먼저 들어간 게 최후에 나가는 자료구조 -> LIFO(Last Input First Output) 구조
- 함수 내의 로컬변수 임시 저장
- 함수 호출 시 파라미터 전달
- 복귀 주소(return address) 저장
• Stack Frame
ESP(스택 포인터)가 아닌 EBP(베이스 포인터) 레지스터를 이용하여 스택 내의 로컬 변수, 파라미터, 복귀 주소 등에 접근하는 기법이다.
ESP 값은 프로그램 안에서 수시로 변하기 때문에 EBP를 함수 시작 전에 저장하고 유지하면 안전하게 변수, 파라미터, 복귀 주소등에 접근할 수 있다.
• 실습(Stack Frame)
소스코드에서의 main의 위치를 찾는다.
00401026 주소를 실행시키면 ebp로 부터 4떨어진 곳에 1을 저장한다. (Stack에 1이 쌓인다)
0040102D 주소를 실행시키면 ebp로부터 8 떨어진 곳에 2을 저장한다.(Stack에 2가 쌓인다)
mov eax, dword ptr ss::[ebp-8] 명령어로 eax에 2를 넣고 push로 스택에 값을 저장한다.
mov ecx, dword ptr ss::[ebp-4] 명령어로 ecx에 1을 넣고 push로 스택에 값을 저장한다.
그다음 call 함수를 사용해 소스코드에서의 add 함수로 보내준다.
0040100은 소스코드 add 함수 시작 부분이다. 스택을 보면 return 값이 00401041로 되어있고 위 스택구조에서 확인했던 거처럼 00401041 return address 주소 밑에는 인자값인 1, 2가 스택에 저장이 되어있다.
• 실습(Crackme2)
접근을 하기 위해서는 임의의 Name, Serial를 넣고 Check를 했을 때 나오는 실행 결과 화면이다.
찾기 기능을 통해 Nope, this serial is wrong! 메시지가 적혀있는 주소로 이동을 한다.
주소 부분에서 위로 올려보니 성공 메시지가 적혀있는 주소가 보인다.
즉, call dword ptr ds:[__vbaVarTstEq>] 주소에서 비교를 한 다음 틀리면 je crackme2.403408 주소에서 점프를 하는 거 같다.
call 주소로 들어가서 위에서 공부한 거처럼 스택을 확인하면 retrun address 주소 다음에 밑에 있는 0019 F298 주소에 있는 인자값이랑 0019 F288 주소에 있는 인자값이랑 비교하는 거 같다.
스택에서 해당 주소로 이동을 해보니까 입력했던 1234 값이 스택에 쌓여있고, 위 부분에 비교하는 다른 인자값이 스택에 쌓여있는 거 같다.
스택에 쌓여있는 인자값을 serial 값에 넣으니 성공 메시지가 출력이 된다.