Post

main startup routine bt

main의 상위 frame은 \_\_libc\_start\_main이다.

__libc_start_main

\_\_libc\_start\_maininit, fini, stack\_end 등을 인자로 받는데, 첫 번째 인자로 main 의 함수 포인터 를 받는다.

1
2
3
4
5
6
7
8
int \_\_cdecl \_libc\_start\_main(int (\_\_cdecl \*main)(int, char \*\*, char \*\*), int argc, char \*\*ubp\_av,
void (\*init)(void), void (\*fini)(void), void (\*rtld\_fini)(void), void \*stack\_end)

  

.text:0000000000000A5D       lea     rdi, main       ; main
.text:0000000000000A64       call    \_\_libc\_start\_main

\_\_libc\_start\_main의 상위 frame은 \_start다.

start ( = Entry point )

OEP(Original Entry Point) = Image Base + Address of Entry Point(RVA)

바이너리에서 코드의 시작 지점은 Image Base + Base of Code지만, 실제로 프로그램이 맨 처음 실행하게 되는 Instruction은 Entry Point 다. 그리고 OEP에는 start가 있다.

* Base of Code와 OEP(Address of Entry Point)는 전혀 관련이 없다. Base of Code는 단순히 코드 섹션이 거기서 부터 시작한다는 것을 의미한다. * Base of Code에는 컴파일러가 포함한 스타트업 루틴 등 stub code가 위치하게 되는데, 단순히 위치 상으로 Address of Entry Point 이전에 있는 코드라고 해서 스타트업 루틴으로 간주해서는 안된다. * 스타트업 루틴 등이 위치한 경우 디버거로 봐도 EIP에 들어가는걸 볼 수 없다. 그런 루틴이 끝나야 디버거에 로드되기 때문.

\_start → \_\_libc\_start\_main → main 순으로 호출하고, main에서 ret\_\_libc\_start\_main의 끝부분 (+255)로 가게 된다. 여기서 call instruction을 수행하면서 어딘가로 가게되는데 dl계열 함수들이나 exit함수를 통해 자원반납이나 종료선행작업을 하는 듯 보인다.

\_\_libc\_start\_main에서 ret\_start+33으로 가게 되는데, 여기서 hlt instruction을 실행하게 된다.

hlt를 실행하면 CPU는 외부 인터럽트가 들어올 때 까지 대기한다.

Windows

Windows도 크게 다르지 않다. start → [jmp : tmainCRTStartup ... call : main] → main 순으로 호출한다.

This post is licensed under CC BY 4.0 by the author.