| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- mr 100
- 라우터
- tl mr 100
- System Management Mode
- exit handler overwrite
- Slab free list poisoning
- exploit
- Cross-cache attack
- hardware hakcing
- 익스플로잇
- protection ring
- 커널
- e
- memory
- tp link
- Router
- mips
- linux ring 권한 구조
- physmap
- UART
- SMM
- kernel exploit
- fini array
- ROP
- Kernel
- openwrt
- Pwnable
- 공유기
- Today
- Total
haehet
프로그램 시작, 종료 과정 및 관련 취약점 분석 본문
최근에 드림핵에서 tiny backdoor 8단계 문제를 풀었는데 .fini.array를 조작해야 하는 문제였다. 이 문제를 풀면서 프로그램의 시작, 종료 관련 취약점에 대해서 정리해야겠다는 생각이 들었다.
*이 글은 (Ubuntu GLIBC 2.35-0ubuntu3.10)을 기준으로 분석했다. 라이브러리 버전마다 약간씩 차이가 있을 수 있다.
또한 gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 기준으로 컴파일을 했다.
아래에 있는 간단한 코드를 통해 분석 해보겠따.
#include <stdio.h>
//gcc -o test test.c
int main(int argc, char* argv)
{
printf("%s", "test\n");
return 0;
}
프로그램 시작 과정
1. execve -> ld.so
우리가 프로그램을 실행 시키면 execve를 통해 프로세스를 생성한다. 그리고 execve는 프로그램의 .interp 섹션에 저장되어 있는 ld.so를 실행 시킨다.
pwndbg> info file
Symbols from "/home/haehet/test".
Local exec file:
`/home/haehet/test', file type elf64-x86-64.
Entry point: 0x1060
0x0000000000000318 - 0x0000000000000334 is .interp
0x0000000000000338 - 0x0000000000000368 is .note.gnu.property
0x0000000000000368 - 0x000000000000038c is .note.gnu.build-id
0x000000000000038c - 0x00000000000003ac is .note.ABI-tag
0x00000000000003b0 - 0x00000000000003d4 is .gnu.hash
0x00000000000003d8 - 0x0000000000000480 is .dynsym
0x0000000000000480 - 0x000000000000050d is .dynstr
0x000000000000050e - 0x000000000000051c is .gnu.version
0x0000000000000520 - 0x0000000000000550 is .gnu.version_r
0x0000000000000550 - 0x0000000000000610 is .rela.dyn
0x0000000000000610 - 0x0000000000000628 is .rela.plt
0x0000000000001000 - 0x000000000000101b is .init
0x0000000000001020 - 0x0000000000001040 is .plt
0x0000000000001040 - 0x0000000000001050 is .plt.got
0x0000000000001050 - 0x0000000000001060 is .plt.sec
0x0000000000001060 - 0x0000000000001172 is .text
0x0000000000001174 - 0x0000000000001181 is .fini
0x0000000000002000 - 0x0000000000002009 is .rodata
0x000000000000200c - 0x0000000000002040 is .eh_frame_hdr
0x0000000000002040 - 0x00000000000020ec is .eh_frame
0x0000000000003db8 - 0x0000000000003dc0 is .init_array
0x0000000000003dc0 - 0x0000000000003dc8 is .fini_array
0x0000000000003dc8 - 0x0000000000003fb8 is .dynamic
0x0000000000003fb8 - 0x0000000000004000 is .got
0x0000000000004000 - 0x0000000000004010 is .data
0x0000000000004010 - 0x0000000000004018 is .bss
pwndbg> x/s 0x0000000000000318
0x318: "/lib64/ld-linux-x86-64.so.2"
pwndbg>
ld.so는 동적 라이브러리 glibc를 프로그램에 매핑 해주고 각종 초기화 작업을 한다.
2. start
ld.so 다음에는 바이너리 내부에 Entry point에 있는 start 함수를 실행 시킨다.
pwndbg> info file
Symbols from "/home/haehet/test".
Local exec file:
`/home/haehet/test', file type elf64-x86-64.
Entry point: 0x1060
0x0000000000000318 - 0x0000000000000334 is .interp
0x0000000000000338 - 0x0000000000000368 is .note.gnu.property
0x0000000000000368 - 0x000000000000038c is .note.gnu.build-id
0x000000000000038c - 0x00000000000003ac is .note.ABI-tag
0x00000000000003b0 - 0x00000000000003d4 is .gnu.hash
0x00000000000003d8 - 0x0000000000000480 is .dynsym
0x0000000000000480 - 0x000000000000050d is .dynstr
0x000000000000050e - 0x000000000000051c is .gnu.version
0x0000000000000520 - 0x0000000000000550 is .gnu.version_r
0x0000000000000550 - 0x0000000000000610 is .rela.dyn
0x0000000000000610 - 0x0000000000000628 is .rela.plt
0x0000000000001000 - 0x000000000000101b is .init
0x0000000000001020 - 0x0000000000001040 is .plt
0x0000000000001040 - 0x0000000000001050 is .plt.got
0x0000000000001050 - 0x0000000000001060 is .plt.sec
0x0000000000001060 - 0x0000000000001172 is .text
0x0000000000001174 - 0x0000000000001181 is .fini
0x0000000000002000 - 0x0000000000002009 is .rodata
0x000000000000200c - 0x0000000000002040 is .eh_frame_hdr
0x0000000000002040 - 0x00000000000020ec is .eh_frame
0x0000000000003db8 - 0x0000000000003dc0 is .init_array
0x0000000000003dc0 - 0x0000000000003dc8 is .fini_array
0x0000000000003dc8 - 0x0000000000003fb8 is .dynamic
0x0000000000003fb8 - 0x0000000000004000 is .got
0x0000000000004000 - 0x0000000000004010 is .data
0x0000000000004010 - 0x0000000000004018 is .bss
pwndbg> x/13i 0x1060
0x1060 <_start>: endbr64
0x1064 <_start+4>: xor ebp,ebp
0x1066 <_start+6>: mov r9,rdx
0x1069 <_start+9>: pop rsi
0x106a <_start+10>: mov rdx,rsp
0x106d <_start+13>: and rsp,0xfffffffffffffff0
0x1071 <_start+17>: push rax
0x1072 <_start+18>: push rsp
0x1073 <_start+19>: xor r8d,r8d
0x1076 <_start+22>: xor ecx,ecx
0x1078 <_start+24>: lea rdi,[rip+0xca] # 0x1149 <main>
0x107f <_start+31>: call QWORD PTR [rip+0x2f53] # 0x3fd8
0x1085 <_start+37>: hlt
start 함수는 각종 register을 초기화 하고 rdi에 main의 주소를 넣은 뒤 특정영역 주소를 실행 시키는데 이 주소가 __libc_start_main_impl의 GOT가 된다.
3. __libc_start_main_impl, _libc_start_call_main -> main 호출
__libc_start_main_impl에서는 각종 인자 세팅 및 점검 후 __libc_start_call_main을 호출 한다.
pwndbg> x/90i 0x7ffff7c29dc0
0x7ffff7c29dc0 <__libc_start_main_impl>: endbr64
0x7ffff7c29dc4 <__libc_start_main_impl+4>: push r15
0x7ffff7c29dc6 <__libc_start_main_impl+6>: mov r15,rcx
0x7ffff7c29dc9 <__libc_start_main_impl+9>: push r14
0x7ffff7c29dcb <__libc_start_main_impl+11>: push r13
0x7ffff7c29dcd <__libc_start_main_impl+13>: mov r13,rdi
0x7ffff7c29dd0 <__libc_start_main_impl+16>: push r12
0x7ffff7c29dd2 <__libc_start_main_impl+18>: mov r12,rdx
0x7ffff7c29dd5 <__libc_start_main_impl+21>: push rbp
0x7ffff7c29dd6 <__libc_start_main_impl+22>: mov ebp,esi
0x7ffff7c29dd8 <__libc_start_main_impl+24>: push rbx
0x7ffff7c29dd9 <__libc_start_main_impl+25>: sub rsp,0x18
0x7ffff7c29ddd <__libc_start_main_impl+29>: test r9,r9
0x7ffff7c29de0 <__libc_start_main_impl+32>: je 0x7ffff7c29dee <__libc_start_main_impl+46>
0x7ffff7c29de2 <__libc_start_main_impl+34>: mov rdi,r9
0x7ffff7c29de5 <__libc_start_main_impl+37>: xor edx,edx
0x7ffff7c29de7 <__libc_start_main_impl+39>: xor esi,esi
0x7ffff7c29de9 <__libc_start_main_impl+41>: call 0x7ffff7c458c0 <__GI___cxa_atexit>
0x7ffff7c29dee <__libc_start_main_impl+46>: mov rax,QWORD PTR [rip+0x1f00d3] # 0x7ffff7e19ec8
0x7ffff7c29df5 <__libc_start_main_impl+53>: mov eax,DWORD PTR [rax]
0x7ffff7c29df7 <__libc_start_main_impl+55>: mov ebx,eax
0x7ffff7c29df9 <__libc_start_main_impl+57>: mov DWORD PTR [rsp],eax
0x7ffff7c29dfc <__libc_start_main_impl+60>: and ebx,0x2
0x7ffff7c29dff <__libc_start_main_impl+63>: jne 0x7ffff7c29ee9 <__libc_start_main_impl+297>
0x7ffff7c29e05 <__libc_start_main_impl+69>: mov rax,QWORD PTR [rip+0x1f01ac] # 0x7ffff7e19fb8
0x7ffff7c29e0c <__libc_start_main_impl+76>: mov rdx,QWORD PTR [rax]
0x7ffff7c29e0f <__libc_start_main_impl+79>: test r15,r15
0x7ffff7c29e12 <__libc_start_main_impl+82>: je 0x7ffff7c29e40 <__libc_start_main_impl+128>
0x7ffff7c29e14 <__libc_start_main_impl+84>: mov rsi,r12
0x7ffff7c29e17 <__libc_start_main_impl+87>: mov edi,ebp
0x7ffff7c29e19 <__libc_start_main_impl+89>: call r15
0x7ffff7c29e1c <__libc_start_main_impl+92>: mov r15,QWORD PTR [rip+0x1f017d] # 0x7ffff7e19fa0
0x7ffff7c29e23 <__libc_start_main_impl+99>: mov rdi,QWORD PTR [r15]
0x7ffff7c29e26 <__libc_start_main_impl+102>: call 0x7ffff7c286d0 <_dl_audit_preinit@plt>
0x7ffff7c29e2b <__libc_start_main_impl+107>: test ebx,ebx
0x7ffff7c29e2d <__libc_start_main_impl+109>: jne 0x7ffff7c29eca <__libc_start_main_impl+266>
0x7ffff7c29e33 <__libc_start_main_impl+115>: mov rdx,r12
0x7ffff7c29e36 <__libc_start_main_impl+118>: mov esi,ebp
0x7ffff7c29e38 <__libc_start_main_impl+120>: mov rdi,r13
0x7ffff7c29e3b <__libc_start_main_impl+123>: call 0x7ffff7c29d10 <__libc_start_call_main>
0x7ffff7c29e40 <__libc_start_main_impl+128>: mov r15,QWORD PTR [rip+0x1f0159] # 0x7ffff7e19fa0
0x7ffff7c29e47 <__libc_start_main_impl+135>: mov r14,QWORD PTR [r15]
0x7ffff7c29e4a <__libc_start_main_impl+138>: mov rcx,QWORD PTR [r14+0xa0]
0x7ffff7c29e51 <__libc_start_main_impl+145>: test rcx,rcx
0x7ffff7c29e54 <__libc_start_main_impl+148>: je 0x7ffff7c29e6c <__libc_start_main_impl+172>
0x7ffff7c29e56 <__libc_start_main_impl+150>: mov QWORD PTR [rsp],rdx
0x7ffff7c29e5a <__libc_start_main_impl+154>: mov rcx,QWORD PTR [rcx+0x8]
0x7ffff7c29e5e <__libc_start_main_impl+158>: mov rsi,r12
0x7ffff7c29e61 <__libc_start_main_impl+161>: mov edi,ebp
0x7ffff7c29e63 <__libc_start_main_impl+163>: add rcx,QWORD PTR [r14]
0x7ffff7c29e66 <__libc_start_main_impl+166>: call rcx
0x7ffff7c29e68 <__libc_start_main_impl+168>: mov rdx,QWORD PTR [rsp]
0x7ffff7c29e6c <__libc_start_main_impl+172>: mov rdi,QWORD PTR [r14+0x108]
0x7ffff7c29e73 <__libc_start_main_impl+179>: test rdi,rdi
0x7ffff7c29e76 <__libc_start_main_impl+182>: je 0x7ffff7c29e23 <__libc_start_main_impl+99>
0x7ffff7c29e78 <__libc_start_main_impl+184>: mov rcx,QWORD PTR [r14+0x118]
0x7ffff7c29e7f <__libc_start_main_impl+191>: mov rsi,QWORD PTR [rcx+0x8]
0x7ffff7c29e83 <__libc_start_main_impl+195>: mov rcx,QWORD PTR [r14]
0x7ffff7c29e86 <__libc_start_main_impl+198>: add rcx,QWORD PTR [rdi+0x8]
0x7ffff7c29e8a <__libc_start_main_impl+202>: shr rsi,0x3
0x7ffff7c29e8e <__libc_start_main_impl+206>: test esi,esi
0x7ffff7c29e90 <__libc_start_main_impl+208>: je 0x7ffff7c29e23 <__libc_start_main_impl+99>
0x7ffff7c29e92 <__libc_start_main_impl+210>: sub esi,0x1
0x7ffff7c29e95 <__libc_start_main_impl+213>: lea r14,[rcx+0x8]
0x7ffff7c29e99 <__libc_start_main_impl+217>: lea rax,[r14+rsi*8]
0x7ffff7c29e9d <__libc_start_main_impl+221>: mov QWORD PTR [rsp+0x8],rax
0x7ffff7c29ea2 <__libc_start_main_impl+226>: jmp 0x7ffff7c29eb0 <__libc_start_main_impl+240>
0x7ffff7c29ea4 <__libc_start_main_impl+228>: nop DWORD PTR [rax+0x0]
0x7ffff7c29ea8 <__libc_start_main_impl+232>: mov rdx,QWORD PTR [rsp]
0x7ffff7c29eac <__libc_start_main_impl+236>: add r14,0x8
0x7ffff7c29eb0 <__libc_start_main_impl+240>: mov QWORD PTR [rsp],rdx
0x7ffff7c29eb4 <__libc_start_main_impl+244>: mov rsi,r12
0x7ffff7c29eb7 <__libc_start_main_impl+247>: mov edi,ebp
0x7ffff7c29eb9 <__libc_start_main_impl+249>: call QWORD PTR [rcx]
0x7ffff7c29ebb <__libc_start_main_impl+251>: mov rcx,r14
0x7ffff7c29ebe <__libc_start_main_impl+254>: cmp QWORD PTR [rsp+0x8],r14
0x7ffff7c29ec3 <__libc_start_main_impl+259>: jne 0x7ffff7c29ea8 <__libc_start_main_impl+232>
0x7ffff7c29ec5 <__libc_start_main_impl+261>: jmp 0x7ffff7c29e23 <__libc_start_main_impl+99>
0x7ffff7c29eca <__libc_start_main_impl+266>: mov rbx,QWORD PTR [rip+0x1efff7] # 0x7ffff7e19ec8
0x7ffff7c29ed1 <__libc_start_main_impl+273>: mov rsi,QWORD PTR [r12]
0x7ffff7c29ed5 <__libc_start_main_impl+277>: lea rdi,[rip+0x1ae0be] # 0x7ffff7dd7f9a
0x7ffff7c29edc <__libc_start_main_impl+284>: xor eax,eax
0x7ffff7c29ede <__libc_start_main_impl+286>: call QWORD PTR [rbx+0x330]
0x7ffff7c29ee4 <__libc_start_main_impl+292>: jmp 0x7ffff7c29e33 <__libc_start_main_impl+115>
0x7ffff7c29ee9 <__libc_start_main_impl+297>: mov rcx,QWORD PTR [rip+0x1effd8] # 0x7ffff7e19ec8
0x7ffff7c29ef0 <__libc_start_main_impl+304>: mov rsi,QWORD PTR [r12]
0x7ffff7c29ef4 <__libc_start_main_impl+308>: lea rdi,[rip+0x1ae085] # 0x7ffff7dd7f80
0x7ffff7c29efb <__libc_start_main_impl+315>: xor eax,eax
0x7ffff7c29efd <__libc_start_main_impl+317>: call QWORD PTR [rcx+0x330]
0x7ffff7c29f03 <__libc_start_main_impl+323>: jmp 0x7ffff7c29e05 <__libc_start_main_impl+69>
__libc_start_call_main은 main에 사용되는 인자를 세팅 한 후 libc_csu_init과 main을 호출 한다. 이 함수는 .initi_array에 있는 함수들을 호출한다. 위 바이너리를 내가 컴파일 했을 때는 libc_csu_init이 나오지 않았다. 최적화 문제인가 싶어서 코드를 길게 짜보아도 왜인지 나오지 않았다. gcc버전 문제인듯 하다. libc_csu_init를 가젯으로 이용하는 기법이 있으므로 찾아보도록 하자.
프로그램 종료 과정
1. __GI_exit
main 함수에서 ret 후 __libc_start_call_main에서는 __GI_exit을 실행 시킨다. __GI_exit은 인자에 __exit_funcs을 넣고 __run_exit_handlers을 호출한다.
pwndbg> x/8i 0x7ffff7c455f0
0x7ffff7c455f0 <__GI_exit>: endbr64
0x7ffff7c455f4 <__GI_exit+4>: push rax
0x7ffff7c455f5 <__GI_exit+5>: pop rax
0x7ffff7c455f6 <__GI_exit+6>: mov ecx,0x1
0x7ffff7c455fb <__GI_exit+11>: mov edx,0x1
0x7ffff7c45600 <__GI_exit+16>: lea rsi,[rip+0x1d5231] # 0x7ffff7e1a838 <__exit_funcs>
0x7ffff7c45607 <__GI_exit+23>: sub rsp,0x8
0x7ffff7c4560b <__GI_exit+27>: call 0x7ffff7c45390 <__run_exit_handlers>
pwndbg> x/6gx 0x7ffff7e1a838
0x7ffff7e1a838 <__exit_funcs>: 0x00007ffff7e1bf00 0x00007ffff7e1c320
0x7ffff7e1a848: 0x0000000000000000 0x0000000000000000
0x7ffff7e1a858: 0x0000000000000000 0x00007ffff7e1a210
pwndbg> x/gx 0x00007ffff7e1bf00
0x7ffff7e1bf00 <initial>: 0x0000000000000000
pwndbg> x/gx 0x00007ffff7e1c320
0x7ffff7e1c320 <initial_quick>: 0x0000000000000000
pwndbg> x/gx 0x00007ffff7e1a210
0x7ffff7e1a210 <randtbl+16>: 0x4e508aaa3e01511e
2. __run_exit_handlers (exit handler overwrite)
__run_exit_handlers은 프로그램 종료시 등록되어 있는 함수들을 실행시키는 함수이다. 코드가 길어서 중요한 부분만 보도록하겠다.
0x00007ffff7c45463 <+211>: mov rax,QWORD PTR [rdx+0x18]
0x00007ffff7c45467 <+215>: mov r13,QWORD PTR [rdx+0x20]
0x00007ffff7c4546b <+219>: mov QWORD PTR [rdx+0x10],0x0
0x00007ffff7c45473 <+227>: mov edx,ebx
0x00007ffff7c45475 <+229>: ror rax,0x11
0x00007ffff7c45479 <+233>: xor rax,QWORD PTR fs:0x30
0x00007ffff7c45482 <+242>: xchg DWORD PTR [r14],edx
0x00007ffff7c45485 <+245>: cmp edx,0x1
0x00007ffff7c45488 <+248>: jg 0x7ffff7c455a0 <__run_exit_handlers+528>
0x00007ffff7c4548e <+254>: mov esi,ebp
0x00007ffff7c45490 <+256>: mov rdi,r13
0x00007ffff7c45493 <+259>: call rax
RDX 0x7ffff7e1bf00 (initial) ◂— 0
여기서 rax에는 initial+0x18의 주소가 들어간다. initial+0x18에서 함수의 주소를 가져온 후 함수의 rdi에는 initial+0x20의 값을 넣는다. 그 후 가져온 함수 주소를 ror 0x11연산을 하고 fs:0x30 값과 xor을 한 후 사용한다. 이 것을 이용해서 glibc 2.35에서 사용 가능한 강력한 기법이 있다.
exit handler overwrite
1. fsbase+0x30 값을 leak 또는 0으로 덮는다.
2. 우리가 넣을 함수 주소가 system이라 하면 mangled_system = fsbase+0x30 ^ (rol system, 0x11)과 같이 계산해준다.
3. initial+0x10에 p64(0x4) + p64(mangled_system) + p64(binsh) 이렇게 쓴다.
3. _dl_fini
__run_exit_handlers는 initial에서 _dl_fini 함수를 실행시킨다. _dl_fini에도 특정 구조체를 덮어서 실행 흐름을 바꾸는 overwrite _rtld_global 기법이 존재한다. 하지만 glibc 2.35에서는 하기 어렵다. 따라서 여기서는 다루지 않겠다.
*RAX 0x7ffff7fc9040 (_dl_fini) ◂— endbr64
RBX 0
*RCX 4
*RDX 1
*RDI 0
*RSI 0
*R8 0
*R9 0x5555555592a0 ◂— 0xa74736574 /* 'test\n' */
*R10 0x77
*R11 0x246
*R12 0x7ffff7e1a838 (__exit_funcs) —▸ 0x7ffff7e1bf00 (initial) ◂— 0
*R13 0
*R14 0x7ffff7e1bee8 (__exit_funcs_lock) ◂— 0
*R15 0x7ffff7e1bf00 (initial) ◂— 0
*RBP 0
*RSP 0x7fffffffdec0 —▸ 0x555555556004 ◂— 0x74736574 /* 'test' */
*RIP 0x7ffff7c45493 (__run_exit_handlers+259) ◂— call rax
────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────
► 0x7ffff7c45493 <__run_exit_handlers+259> call rax <_dl_fini>
_dl_fini는 .fini_array에 있는 값들을 호출 한다.
0x00007ffff7fc9242 <+514>: nop WORD PTR [rax+rax*1+0x0]
0x00007ffff7fc9248 <+520>: mov QWORD PTR [rbp-0x38],rax
0x00007ffff7fc924c <+524>: call QWORD PTR [rax]
RAX 0x555555557dc0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x555555555100 (__do_global_dtors_aux) ◂— endbr64
0x0000555555557dc0 - 0x0000555555557dc8 is .fini_array
여기서 또 가능한 기법이 있다.
.fini_array overwrite
No RELRO일때 .fini_array를 덮으면 우리가 원하는 함수 실행이 가능하다.
4. _fini
_dl_fini는 _fini라는 함수를 실행 시키는데 딱히 하는 동작이 없는 함수이다.
0x00007ffff7fc926b <+555>: mov rax,QWORD PTR [rax+0x8]
0x00007ffff7fc926f <+559>: add rax,QWORD PTR [r15]
0x00007ffff7fc9272 <+562>: call rax
RAX 0x555555555174 (_fini) ◂— endbr64
pwndbg> x/4i 0x555555555174
0x555555555174 <_fini>: endbr64
0x555555555178 <_fini+4>: sub rsp,0x8
0x55555555517c <_fini+8>: add rsp,0x8
0x555555555180 <_fini+12>: ret
5. __GI__exit
_dl_fini가 종료되고 __run_exit_handlers로 돌아오면 __GI__exit를 실행 시킨다. 이 함수는 처음에 설명한 함수와 다른 함수이다.(_가 하나 더있다) 이 함수는 syscall 231번(sys_exit_group)을 통해 프로그램을 종료시킨다.
pwndbg> disass __GI__exit
Dump of assembler code for function __GI__exit:
0x00007ffff7fe9e90 <+0>: endbr64
0x00007ffff7fe9e94 <+4>: mov esi,0xe7
0x00007ffff7fe9e99 <+9>: mov edx,0x3c
0x00007ffff7fe9e9e <+14>: jmp 0x7ffff7fe9ead <__GI__exit+29>
0x00007ffff7fe9ea0 <+16>: mov eax,edx
0x00007ffff7fe9ea2 <+18>: syscall
0x00007ffff7fe9ea4 <+20>: cmp rax,0xfffffffffffff000
0x00007ffff7fe9eaa <+26>: ja 0x7ffff7fe9ec8 <__GI__exit+56>
0x00007ffff7fe9eac <+28>: hlt
0x00007ffff7fe9ead <+29>: mov eax,esi
0x00007ffff7fe9eaf <+31>: syscall
0x00007ffff7fe9eb1 <+33>: cmp rax,0xfffffffffffff000
0x00007ffff7fe9eb7 <+39>: jbe 0x7ffff7fe9ea0 <__GI__exit+16>
0x00007ffff7fe9eb9 <+41>: neg eax
0x00007ffff7fe9ebb <+43>: mov DWORD PTR [rip+0x143df],eax # 0x7ffff7ffe2a0 <rtld_errno>
0x00007ffff7fe9ec1 <+49>: jmp 0x7ffff7fe9ea0 <__GI__exit+16>
0x00007ffff7fe9ec3 <+51>: nop DWORD PTR [rax+rax*1+0x0]
0x00007ffff7fe9ec8 <+56>: neg eax
0x00007ffff7fe9eca <+58>: mov DWORD PTR [rip+0x143d0],eax # 0x7ffff7ffe2a0 <rtld_errno>
0x00007ffff7fe9ed0 <+64>: jmp 0x7ffff7fe9eac <__GI__exit+28>
이번 글에서는 프로그램의 시작, 종료 과정과 그와 관련된 취약점에 대해 알아보았다. 여기에서 설명한 시작, 종료 함수 외에도 많은 함수가 존재하는 것 같다.
'Pwnable' 카테고리의 다른 글
| MIPS Architecture Exploitation (0) | 2026.05.01 |
|---|---|
| tcache_perthread_struct overwriting (0) | 2026.01.26 |
| FSOP 정리 (0) | 2025.11.08 |
| heap exploit 정리 (0) | 2025.11.05 |
| side channel attack(with assembly) (0) | 2025.10.02 |
