Reversing Engineering quotedb.exe (bmdyy) Bypass ASLR+DEP
Table of Contents
I’m continuing to study for my OSED Exam, I downloaded the quotedb.exe developed by bmdyy. You can download here QuoteDB.exe
We will use windbg and IDA Free to uncover vulnerabilities and exploit, the QuoteDB.exe has been compiled with ASLR and DEP enabled. If you haven’t seen, please check my post about DEP: Demystifying DEP (Data Execution Prevention). We will also bypass ASLR by leaking the address returned to us, lets start and stop talking 👽.
Enumerating the Software #
One step really important is software enumeration, we will run the application and observe all available functionality that receives input either from user or application itself through its configuration files, registry keys etc. One of the tool commonly used for software enumeration is sysinternal from Microsoft where we can observe port listening, what files or registry keys the software is trying to access etc.
After you download the QuoteDB.exe, lets run and observe the software running using TCPView one of the sysinternal tools.
Just observing the output we can learn a lot, the software adds some data to db and we don’t know yet if its writing the data to a file or memory at this point, know they call it as “quote” and the software initializes the WSA and network Socket and bound to 3700 TCP port. Using TCPView we can confirm is indeed listeninig on port 3700 TCP Protocol.
ASLR and DEP Enabled #
We can use the narly plugin to check binary protections enabled on quotedb.exe. We can use windbg to attach to quotedb.exe process and run the command below to load the plugin.
.load narly.dll
We can run !nmod to check protections and we see *ASLR and *DEP are enabled on QuoteDB process. That means we will need to bypass the protections to be successful.
0:001> !nmod
01000000 01052000 QuoteDB /SafeSEH OFF *ASLR *DEP C:\Users\kali\Desktop\ExpDev_Traning\QuoteDB.exe
747c0000 74816000 mswsock /SafeSEH ON /GS *ASLR *DEP C:\Windows\system32\mswsock.dll
75290000 754c8000 KERNELBASE /SafeSEH ON /GS *ASLR *DEP C:\Windows\System32\KERNELBASE.dll
76ac0000 76b23000 WS2_32 /SafeSEH ON /GS *ASLR *DEP C:\Windows\System32\WS2_32.dll
76b30000 76bf3000 RPCRT4 /SafeSEH ON /GS *ASLR *DEP C:\Windows\System32\RPCRT4.dll
76e00000 76ebf000 msvcrt /SafeSEH ON /GS *ASLR *DEP C:\Windows\System32\msvcrt.dll
76f50000 76fea000 KERNEL32 /SafeSEH ON /GS *ASLR *DEP C:\Windows\System32\KERNEL32.DLL
77060000 771ff000 ntdll /SafeSEH ON /GS *ASLR *DEP C:\Windows\SYSTEM32\ntdll.dll
*DEP/*ASLR means that these modules are compatible with ASLR/DEP
Reverse Engineering QuoteDB.exe #
After we have discovered the software is listening on 3700 port, we can use static and dynamic tools to understand more about the QuoteDB.exe.
For static anlysis we will use IDA Free and windbg for dynamic analysis. Lets decompile QuoteDB.exe with IDA Free and Sync with Windbg.Open the quotedb.exe on IDA Free and also open windbg and attach to the running quotedb.exe process. After you attach with windbg to QuoteDB.exe you should see similar information, on your machine might change the memory address, you need to make sure the base address for QuoteDB.exe is matched with the one in IDA Free, you can see in windbg shows QuoteDB.exe base address is 0x01000000.
Symbol search path is: srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 01000000 01052000 C:\Users\kali\Desktop\ExpDev_Traning\QuoteDB.exe
ModLoad: 77060000 771ff000 C:\Windows\SYSTEM32\ntdll.dll
ModLoad: 76f50000 76fea000 C:\Windows\System32\KERNEL32.DLL
ModLoad: 75290000 754c8000 C:\Windows\System32\KERNELBASE.dll
ModLoad: 76e00000 76ebf000 C:\Windows\System32\msvcrt.dll
ModLoad: 76ac0000 76b23000 C:\Windows\System32\WS2_32.dll
ModLoad: 76b30000 76bf3000 C:\Windows\System32\RPCRT4.dll
ModLoad: 747c0000 74816000 C:\Windows\system32\mswsock.dll
(19b0.26e0): Break instruction exception - code 80000003 (first chance)
eax=012c2000 ebx=00000000 ecx=7712b430 edx=7712b430 esi=7712b430 edi=7712b430
eip=770f2770 esp=017ff7f8 ebp=017ff824 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!DbgBreakPoint:
770f2770 cc int 3
Now we need to check in IDA Free, please go to “Edit -> Segments -> Rebase Program…” and if “Image Base” doesn’t match with 0x01000000 (yours might be different), you need to update and click on Ok Button.

Hooking Windbg to WS2_32!recv #
To be able to understand better the software we need to hook the software to the function that will receive the data on port 3700. How to find what function the software is using to receive the data? you can look in the IAT using IDA and see the networking function, most of the time the software will use the recv function from kernel32 or WS2_32 module, you have to determine. In our case if you look at IMPORTS tab in IDA Free and search for recv funtion, we can see its using the WS2_32 module.
We just need to set a breakpoint on WS2_32!recv in windbg as showing below with bp command, the bp set a breakpoint, type g and hit enter to let the debugger continue the execution.

Sending a dummy packet #
Next step write a small python script to send a dummy data allowing us to analyse the software flow using IDA Free and Windbg to follow along. Below is a PoC python script I created.
You can run the script as:- python.exe poc-quote.py <IP>
import socket
import sys
def main():
if len(sys.argv) != 2:
print("Usage: %s <ip_address>\n" % (sys.argv[0]))
sys.exit(1)
server = sys.argv[1]
port = 3700
buf = bytearray([0x41]*0x1000)
s = socket.socket()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((server,port))
s.send(buf)
resp = s.recv(1024)
print("Response: ",resp)
print("[+] Packet Crash Sent")
sys.exit(0)
if __name__ == '__main__':
main()
We can see the breakpoint is hit, and the memory address will contain our buffer at 017fbb34. We can set a read hardware breakpoint to see where our payload will be used, you can see that out payload is been stored in eax and will be saved in ebp-4034h.
0:001> bp WS2_32!recv
0:001> g
Breakpoint 0 hit
eax=000000c0 ebx=01ab0f78 ecx=00000000 edx=017fbb34 esi=0100173b edi=76e66bc0
eip=76ad23a0 esp=017f7308 ebp=017ffb64 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
WS2_32!recv:
76ad23a0 8bff mov edi,edi
0:001> dds esp l6
017f7308 01001790 QuoteDB+0x1790
017f730c 000000c0
017f7310 017fbb34
017f7314 00004000
017f7318 00000000
017f731c 00000000
0:001> ba r1 017fbb34
0:001> g
Breakpoint 1 hit
eax=41414141 ebx=01ab0f78 ecx=1ff2004a edx=00000000 esi=0100173b edi=76e66bc0
eip=010017e8 esp=017f730c ebp=017ffb64 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
QuoteDB+0x17e8:
010017e8 8985ccbfffff mov dword ptr [ebp-4034h],eax ss:0023:017fbb30=00000000
Analysing the code block in IDA #
Now we can copy the memory address 0x010017e8 and search in IDA Free to understand the code block. You can use “g” keyboard key to jump to address using a memory address

I like to add comments to the assembly instructions that I have control. The following are important instructions to understand:
- 0x0100180D - Maximum buffer size is 0x4000 bytes that means we can send a maximum 0x4000 bytes for our payload.
- 0x010017E2 - eax will contain our controlled buffer
- 0x010017E8 - eax will copy first 4 bytes of our payload in ebp+var_4034
- 0x01001847 - our payload ebp+var_4034 will be copied again into eax
- 0x0100184D - eax (our 4 bytes payload) will be substracted by 0x384 bytes
- 0x01001852 - eax will be compared with 4 if eax <= 4, won’t take the jump only if > 4.
We can learn that first 4 bytes is substracted by 0x384 and compared with 4, this block is a switch statement and based on the opcode number we provide that will take us to jump to different code blocks.
add_quote function #
After spending some time reverse engineering you will notice the 902 (0x386) opcode will take us to the add_quote function. The function will add data of 0x800 bytes into memory address.

get_quote function #
Next we see there is a function called get_quote and the opcode is 901 (0x385), the get_quote has two arguments the index that will be used to retrieve the data and the buffer memory address to write it back into a different memory address.

get_quote snprintf vulnerablity #
If we analyse the get_quote function in IDA, we will se the _snprintf function is vulnerable to format string attack. By sending the payload with %x we can leak a memory address in the stack, and its sent to us via networking packet, and that’s handy because the quotedb.exe is compiled with ASLR enabled, this will allow us to bypass ASLR.

buffer overflow #
If we feed the program with an invalid opcode, the program will call the _log_bad_request function, this function is vulnerbale to buffer overflow if we send a large enough buffer. We can observe below that the issue is the memset function allocates only 0x800 and memcpy maximum size is 0x4000, if we send larger buffer bigger than 0x800 bytes, we can overflow the buffer.

Steps to Develop the Exploit #
Now that we understood the major functions like add_quote, get_quote and how to trigger the vulnerability, we need to develop an exploit that will bypass ASLR and DEP. I already wrote a working PoC that you can follow, you can check quotedb POC
- Send a packet to trigger add_quote via opcode 902 (0x386)
- Send a second packet to trigger the get_quote via opcode 901 (0x385) to leak a module to bypass ASLR
- send another packet to trigger buffer overflow with an invalid opcode and large buffer to overflow.
- We developed ROP (Returned Oriented Programming) to bypass DEP and execute our shellcode.
I hope you enjoy and see you on next post 😄