Featured image of post pwnable.kr random

pwnable.kr random

Write-up

처음 접속을 하면 아래의 코드가 주어진다. 코드를 해석해보면 key와 random을 xor연산하여 0xdeadbeef 와 값이 동일하면 플래그가 출력되도록 되어있다.

random@pwnable:~$ ls
flag  random  random.c
random@pwnable:~$ cat random.c  

#include <stdio.h>

int main(){
	unsigned int random;
	random = rand();	// random value!

	unsigned int key=0;
	scanf("%d", &key);

	if( (key ^ random) == 0xdeadbeef ){ // key random이랑 xor 연산
		printf("Good!\n");
		system("/bin/cat flag");
		return 0;
	}

	printf("Wrong, maybe you should try 2^32 cases.\n");
	return 0;
}

이제 디컴파일을 하여 코드를 확인해보자. DWORD PTR [rbp-0x4],eax에 랜덤값을 생성하여 변수에 삽입하는 것을 알 수 있다.

(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x00000000004005f4 <+0>:	push   rbp
   0x00000000004005f5 <+1>:	mov    rbp,rsp
   0x00000000004005f8 <+4>:	sub    rsp,0x10
   0x00000000004005fc <+8>:	mov    eax,0x0
   0x0000000000400601 <+13>:	call   0x400500 <rand@plt>
   0x0000000000400606 <+18>:	mov    DWORD PTR [rbp-0x4],eax
   0x0000000000400609 <+21>:	mov    DWORD PTR [rbp-0x8],0x0
   0x0000000000400610 <+28>:	mov    eax,0x400760
   0x0000000000400615 <+33>:	lea    rdx,[rbp-0x8]
   0x0000000000400619 <+37>:	mov    rsi,rdx
   0x000000000040061c <+40>:	mov    rdi,rax
   0x000000000040061f <+43>:	mov    eax,0x0
   0x0000000000400624 <+48>:	call   0x4004f0 <__isoc99_scanf@plt>
   0x0000000000400629 <+53>:	mov    eax,DWORD PTR [rbp-0x8]
   0x000000000040062c <+56>:	xor    eax,DWORD PTR [rbp-0x4]
   0x000000000040062f <+59>:	cmp    eax,0xdeadbeef
   0x0000000000400634 <+64>:	jne    0x400656 <main+98>
   0x0000000000400636 <+66>:	mov    edi,0x400763
   0x000000000040063b <+71>:	call   0x4004c0 <puts@plt>
   0x0000000000400640 <+76>:	mov    edi,0x400769
   0x0000000000400645 <+81>:	mov    eax,0x0
   0x000000000040064a <+86>:	call   0x4004d0 <system@plt>
   0x000000000040064f <+91>:	mov    eax,0x0
   0x0000000000400654 <+96>:	jmp    0x400665 <main+113>
   0x0000000000400656 <+98>:	mov    edi,0x400778
   0x000000000040065b <+103>:	call   0x4004c0 <puts@plt>
   0x0000000000400660 <+108>:	mov    eax,0x0
   0x0000000000400665 <+113>:	leave
   0x0000000000400666 <+114>:	ret
End of assembler dump.

해당 지점에서 bp를 잡고 할당된 값을 보면 0x6b8b4567 값이 고정되서 들어가는 것을 알 수 있다. 즉 0x6b8b4567과 0xdeadbeef를 xor연산하여 대입하면 flag를 획득할 수 있다는 것이다.

(gdb) b *main+18
Breakpoint 1 at 0x400606
(gdb) r
Starting program: /home/random/random
Breakpoint 1, 0x0000000000400606 in main ()
(gdb) info register $eax
eax            0x6b8b4567	1804289383

이를 기반으로 아래 코드를 작성하여 flag를 획득 할 수 있었다.

from pwn import *

rand = 0x6b8b4567
deadbeef = 0xdeadbeef
payload = str(deadbeef ^ rand)

s = ssh('random','pwnable.kr',password='guest',port=2222)
p = s.process('./random')

p.sendline(payload)

p.interactive()
 python3 ./pwnable.kr_random.py
[+] Connecting to pwnable.kr on port 2222: Done
[*] passcode@pwnable.kr:
    Distro    Ubuntu 16.04
    OS:       linux
    Arch:     amd64
    Version:  4.4.179
    ASLR:     Enabled
[+] Starting remote process bytearray(b'./random') on pwnable.kr: pid 59043
[*] Switching to interactive mode
Good!
Mommy, I thought libc random is unpredictable...
comments powered by Disqus