Wargame & CTF/pwnableKR

Toddler(random)

g.s.song 2023. 11. 26. 16:24

문제

Daddy, teach me how to use random value in programming!

ssh random@pwnable.kr -p2222 (pw:guest)

 

풀이

 

서버에 접속하여 ls 명령을 입력해보면 random, random.c, flag 3개의 파일이 존재하는 것을 알 수 있습니다. 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 ){
        printf("Good!\n");
        system("/bin/cat flag");
        return 0;
    }
    printf("Wrong, maybe you should try 2^32 cases.\n");
    return 0;
}

입력 받은 key와 random 함수를 통해 생성된 값을 XOR 연산하여 그 값이 0xdeadbeef 이면 플래그를 출력합니다. rand 함수의 경우 seed 값이 없으면 매번 똑같은 값을 생성하게 됩니다. 이를 이용하여 문제 해결이 가능합니다. 분석을 통해 random 변수의 값을 찾고 XOR 연산을 통해 조건을 만족 시킬 수 있습니다.

(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.
(gdb)

random 변수의 위치를 찾기 위해 rand 함수가 실행된 다음인 main+18에 브레이크 포인트를 걸고 디버깅을 시작합니다.

(gdb) b *main+18
Breakpoint 1 at 0x400606
(gdb) r
Starting program: /home/random/random
Breakpoint 1, 0x0000000000400606 in main ()
(gdb) i r
rax            0x6b8b4567    1804289383
rbx            0x0    0
rcx            0x7f16c7ee10a4    139735820275876
rdx            0x7f16c7ee10a8    139735820275880
rsi            0x7ffcec99c17c    140724277985660
rdi            0x7f16c7ee1620    139735820277280
rbp            0x7ffcec99c1b0    0x7ffcec99c1b0
rsp            0x7ffcec99c1a0    0x7ffcec99c1a0
r8             0x7f16c7ee10a4    139735820275876
r9             0x7f16c7ee1120    139735820276000
r10            0x47f    1151
r11            0x7f16c7b57f60    139735816568672
r12            0x400510    4195600
r13            0x7ffcec99c290    140724277985936
r14            0x0    0
r15            0x0    0
rip            0x400606    0x400606 <main+18>
eflags         0x202    [ IF ]
cs             0x33    51
ss             0x2b    43
ds             0x0    0
es             0x0    0
fs             0x0    0
gs             0x0    0
(gdb)

rax 레지스터의 값이 rand 함수를 거친 random 변수의 값입니다. 0x6b8b4567과 0xdeadbeef를 XOR 하면 조건을 만족하는 값이 나올 것입니다.

random@ubuntu:~$ python
Python 2.7.12 (default, Jul  1 2016, 15:12:24)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x6b8b4567^0xdeadbeef
3039230856
>>exit()
random@ubuntu:~$ ./random
3039230856
Good!
Mommy, I thought libc random is unpredictable...
random@ubuntu:~$