Aaron Imperial

Vulnerability research guy who's constantly learning new ways to break software.

BFS Ekoparty 2019 Exploitation Challenge - Override Banking Restrictions to get US Dollars

27 Oct 2019 » security

FROM CRASH TO CODE EXECUTION

this is my first time giving a try into a windows x64 bits , and challenges offered by blue frost security

I’ve decided to give the 2019 BFS Exploitation Challenge a try. It is a Windows 64 bit executable\ for which an exploit is expected to work under Windows 10 Redstone 6

The Rules

  1. Bypass ASLR remotely
  2. 64-bit version exploitation
  3. Remote Execution

Inital Steps

we were given a windows binary only . this made me think, I cannot use any fuzzing technique because I dont know if it’s local or remote . let’s try doing some reverse engineering before, So I can understand what it is really doing.

Navigating through the main function , we notice that it is a remote application which listen to 54321

server

Identifying the Vulnerability

by disassembly the function , it is obvious that some checks need to bypassed in order to send send our payload correctly

checks

  1. if ( v6 == 16i64 )
  2. if ( *(_QWORD *)buf == ‘0x393130326F6B45’ )
  3. strcpy(buf, “Eko2019”);
  4. if ( size_data <= 512 )
  5. if ( (signed int)size_data % 8 )

the first validation our application is checking if our payload is equal to 16 bytes , then if buf is equal to 0x393130326F6B45 which trasnalte into 9102okE in hex. there is a strcpy that copy at the end of our payload Eko2019 , but we also have a size data validation which\ we cannot send more than 512 bytes , and it needs to be aligned correctly for 8 bytes. meaning we could send 8,16,24 so on

the “jle” instruction indicates a signed integer comparison, but later passed as unsigned which lead us an integer overflow

checks

after we successfully send a bigger payload, I notice it crashes after sending 229 bytes , but before that there is a instruction lea rcx, unk_7FF6A8A9E520, but what unk_7FF6A8A9E520 is holding or doing? after inspectioning deeper about this unk_7FF6A8A9E520 . we found there is an array with an offset of 256 with this structure

array_ret

the functionsub_7FF6A8A91000 will return our byte + 488B01C3C3C3C3h in this case 41 48 8B 01 C3 C3 C3 C3

this value will basically be used in the WriteProcessMemory(v2, sub_7FF7DD111000, &Buffer, 8ui64, &NumberOfBytesWritten); as buffer these to the function sub_7FF6A8A91000 as instructions allowing to control what we can execute when we reach it.

overwrite

we could see rax , and rcx was overwritten , but however rax was overwritten only one byte from the lower bytes, and rcx overwrite completely causing an access violation

.text:00007FF7DD111000 arg_0= qword ptr  8
.text:00007FF7DD111000
.text:00007FF7DD111000 db      42h
.text:00007FF7DD111000 mov     rax, [rcx]
.text:00007FF7DD111004 retn

why does this happen?

there’s a reason

  1. because of the value of the pointer of RCX that you control

Strategy

In order to bypass ASLR, we need to cause the server to leak an address that belongs to its process space. Fortunately, there is a call to the send() function , which sends 8 bytes of data, so exactly the size of a pointer in 64 bit land. That should serve our purpose just fine.

          qword_7FF7DD11D4E0 = printf(aRemoteMessageI, (unsigned int)counter_conection, &Dst);
          ++counter_conection;
          Buffer = what_the_heck_do(array[byte % -256]);
          v2 = GetCurrentProcess();
          WriteProcessMemory(v2, sub_7FF7DD111000, &Buffer, 8ui64, &NumberOfBytesWritten);
          *(_QWORD *)v3 = sub_7FF7DD111000(v9);
          send(s, v3, 8, 0);
          result = 1i64;

The strategy is getting control of the “byte” variable Luckily, it is a stack variable adjacent to the “size_data[512]” other than the default one at index 62 (0x3e).

I wrote a simple script to find gadgets in order to leak data from the running process

for i in $(cat file); do echo -e "\n$i" && rasm2 -b -D $i;done

after sometime research how I can read some information about the running process . I found what I could read via gs(segment register) because of x64 bits

0x65488B01C3C3C3C3
0x00000000   4                 65488b01  mov rax, qword gs:[rcx]
0x00000004   1                       c3  ret
0x00000005   1                       c3  ret
0x00000006   1                       c3  ret
0x00000007   1                       c3  ret

So this special register which could lead us to read _PEB , and our peb offset is at +0x060 ProcessEnvironmentBlock : Ptr64 _PEB via dt ntdll!_TEB

preparing our exploit

Leaking the PEB

  1. 0x65 = mov rax, qword gs:[rcx]
  2. 0x060 = _PEB
WINDBG>dt ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x038 EnvironmentPointer : Ptr64 Void
   +0x040 ClientId         : _CLIENT_ID
   +0x050 ActiveRpcHandle  : Ptr64 Void
   +0x058 ThreadLocalStoragePointer : Ptr64 Void
   +0x060 ProcessEnvironmentBlock : Ptr64 _PEB
   +0x068 LastErrorValue   : Uint4B
   +0x06c CountOfOwnedCriticalSections : Uint4B
   +0x070 CsrClientThread  : Ptr64 Void
   +0x078 Win32ThreadInfo  : Ptr64 Void
   +0x080 User32Reserved   : [26] Uint4B

in order to make our exploit to leak the data . we need to find a way to derefence rcx with our _PEB offset\ So we can leak our PEB address to start leaking data to bypass ASLR

leak_peb

Leaking the ImageBaseAddress

WINDBG>dt ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 BitField         : UChar
   +0x003 ImageUsesLargePages : Pos 0, 1 Bit
   +0x003 IsProtectedProcess : Pos 1, 1 Bit
   +0x003 IsImageDynamicallyRelocated : Pos 2, 1 Bit
   +0x003 SkipPatchingUser32Forwarders : Pos 3, 1 Bit
   +0x003 IsPackagedProcess : Pos 4, 1 Bit
   +0x003 IsAppContainer   : Pos 5, 1 Bit
   +0x003 IsProtectedProcessLight : Pos 6, 1 Bit
   +0x003 IsLongPathAwareProcess : Pos 7, 1 Bit
   +0x004 Padding0         : [4] UChar
   +0x008 Mutant           : Ptr64 Void
   +0x010 ImageBaseAddress : Ptr64 Void this our value we want to leak now 
   +0x018 Ldr              : Ptr64 _PEB_LDR_DATA
   +0x020 ProcessParameters : Ptr64 _RTL_USER_PROCESS_PARAMETERS
   +0x028 SubSystemData    : Ptr64 Void
   +0x030 ProcessHeap      : Ptr64 Void
   +0x038 FastPebLock      : Ptr64 _RTL_CRITICAL_SECTION
   +0x040 AtlThunkSListPtr : Ptr64 _SLIST_HEADER
   +0x048 IFEOKey          : Ptr64 Void
   +0x050 CrossProcessFlags : Uint4B
   ....snip

Code execution

overwrite