목록보안 (29)
Jiyong's STUDY

push 14 push 0a 을 보아 함수 1에서 인자로 0x14, 0x0A (10진수로 20과 10) 두 개를 받았다. 이후 call cdecl.00401000에서 mov eax, dword ptr ss:[ebp+8] add eax, dword ptr ss:[ebp+c] 에서 ebp+8과 ebp+c는 앞서 받은 인자 10과 20이다. 즉, 함수2는 10+20 연산을 하는 함수라고 볼 수 있다. 리턴 이후 함수1에서 add esp,8에서 알 수 있는 내용으로는 4byte짜리 인자를 두 개 받았다는 것이며, _cdecl을 사용한 함수다. xor eax, eax는 같으면 eax에 0을 저장한다.
#define _CRT_SECURE_NO_WARNINGS #include #include int main() { int num = 0, i = 0, j = 0, sum = 0, temp = 0; int* atm = NULL; scanf(" %d", &num); atm = (int*)malloc(sizeof(int) * num); for (i = 0; i

여기서 Hello.00501000이 main 함수라는 것을 알 수 있다. F7로 자세히 들어가보면 esi(source index)에 printf의 위치가 저장되고 edi에는 10이 저장되며 시작함. 반복문에서 jnz의 조건이 맞으면 00501010으로 돌아가게 된다. jnz의 flag는 edi이며, 루프문 안에는 dec edi로 루프를 돌 때마다 --연산이 된다. 반복하는 내용은 "Hello.."를 push한 후에 esi를 호출하여(printf 함수) 출력한다. 10번 반복 후엔 그대로 리턴 후에 main 함수를 종료하며 프로그램이 종료된다.

함수 진입때의 EBP는 00D9FCB0었고 프롤로그 이후 바뀌었으나 에필로그 이후 다시 00D9FCB0으로 돌아왔다. push ebp로 함수 진입시의 ebp값을 스택에 저장한 이후에 mov ebp, esp로 ebp에 esp의 값을 저장하고 함수가 끝날 때 esp와 ebp가 원상복구 되면서 함수 진입 직전의 주소를 기억하며 돌아갈 수 있는 것이다. main 함수에서 f1 함수로 진입하여 연산 후 리턴하여 main 함수로 돌아가는 구조인데, esp 하나뿐이면 esp는 함수 안에서 계속해서 바뀌기 때문에 다시 돌아갈 수 없다. 그렇기에 ebp에 저장을 해둔 뒤에 돌아갈 수 있는 것이다. 쉽게 함수는 자신만의 공간을 가지게 되며, 이를 스택프레임이라 한다.
바이트 저장 순서는 엔디언(endian)이라 한다. 우리가 흔히 사용하는 순서는 빅 엔디언이다. 이것의 반대 방향은 리틀 엔디언이라고 한다. 0x12345678이라는 dword값이 있을 때, 12 34 56 78 이렇게 읽어나가면 빅 엔디언이고 78 56 34 12 이렇게 읽어나가면 리틀 엔디언이다. 이것은 인텔 CPU에서 채택한 방법이다. 리버싱을 할 때 보통 2바이트나 4바이트 값은 리틀 엔디언을 사용한다고 생각하자.

module has entry point outside the code와 같은 문제가 발생한다면 코드를 빌드할 때 debug로 하지 말고 release로 빌드하면 된다. 아무튼 빌드한 exe 프로그램을 ollydbg에 올리면 이런 화면이 나오는데 여기서 Hello World!를 출력하는 부분을 찾아야 한다. F7(함수 내로 들어감)이나 F8로 한 줄씩 실행하며 가다가 프로그램에서 Hello World!가 출력되는 부분을 찾으면 F2로 BP를 찍어두고 Ctrl+F2로 재실행하면 된다. 또는 Ctrl+G로 main 함수를 찾을 수도 있다. 아무튼 찾은 이후 아래 Dump Window에서 Ctrl+G로 주소를 검색하면 이제 메모리에 직접 접근하여 수정을 할 수 있다. 다만 여기서 직접 수정하는 경우엔 Hell..