How can I modify an existing executable, such as PuTTY, to insert Donut-generated shellcode, allowing another program (such as the calculator) to be executed before returning to normal PuTTY execution, while ensuring that the process is not killed by the shellcode’s return?
Hello everyone.
Here’s a little problem I’m having, and I’d like to know if you have any ideas.
This might be a bit of a stretch, as I haven’t mastered the whole concept myself.
Here’s what I’m trying to do:
Successful stage = ✓
Step not yet successful = ✗
- Code a c++ program and output an .exe (calc .exe) ✓
- No matter how useful the first program ✓
- Retrieve shellcode via donut (http://github.com/TheWover/donut) ✓
- Retrieve bytes from this shellcode (calc .exe) ✓
- Decompile putty (here, for the example, it doesn’t matter which exe is used) ✓
- We’ll have previously modified putty with a “cave code” to insert our shellcode ✓
- Change the first assembler instructions and jump just the assembler instruction ✓
- Execute the donut shellcode (from my calculator opening) ✓
- When the calculator has run, return to the beginning of the putty instructions ✗
- To do this, you absolutely must exit the shellcode before the return of calc .exe, kills the whole process ✗
- Continue executing putty ✗
In the end, we’ll have the calculator open and then putty’s Ui open, operating normally.
In detail:
all in 32 bits
I code a small program, for example an .exe that opens the calculator on Windows with Visual Studio Community.
I output a shellcode with Windows donut: “donut.exe -i calc.exe -z 2 -x 3 -f 1”.
– Compression 2, Exit block in thread, Format .bin binaries
A shellcode came out with the loader around it. And the shellcode bytes are absolutely not the same as the calc.exe bytes.
In fact, the loader builds the .exe inside the main thread thanks to the shellcode.
Then I use x32dgb and unpack putty. I jump to the place of my “code cave”, then I paste my shellcode, finally at the end of the shellcode execution I jump back to the putty instruction from which I started.
The problem:
In all c++ compilations, there’s a return (even when you haven’t set one).
It’s a condition of the program syntax.
There’s a return in the .exe (calc.exe) but there’s also a return at the end of the donut loader (or a block in the thread so as never to kill it).
I therefore need to bypass these two returns (or blocks), before jmping on the first putty instructions.
What I tried:
-
I decompiled calc.exe to put null bytes in place of the return.
- I took out the shellcode and put it in putty, the calculator starts but I get an exeception error on the null bytes I changed.
- The problem is that it’s in the thread and it’s built from the shellcode, so it’s impossible to write to that memory location.
-
I followed the instructions to the return of my program (1,000,000 instuctions, yes it was long). Hoping to be able to jmp to the first instructions of putty, but the loader builds the .exe (the instructions are the same as calc.exe decompiler) so it’s the main thread and the memory area is not writable (not possible to change the properties of a tread).
Solution?
I’m a bit stuck, but I’m open to suggestions.
- Try a loader that doesn’t kill the thread? (but it doesn’t solve the problem of the return in calc.exe)
- Decompile calc.exe, change the return by a jump in putty? (But then you have to guess the offset of putty in the decompilation of calc.exe and the offsets are random at each new execution)
- Find in the loader / shellcode (in bytes) the exact place where is the build of the calc.exe return to jump from the to putty (The shellcode is ~~ 25ko so you know it’s a lot of bytes to search by hand)
mashal lah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.