2

I'm kind of new to this sort of thing so I hope someone can help me. I'm currently trying to understand how most malwares infect other files/modify an exe. Using Visual Studio 2017 I made an exe (with c++) that only does 2 things: print "Injection didn't work!" and after that runs "pause>NUL". I compiled it in x86 Release mode. Then I made a second exe which only prints "Injection worked". My main goal was to inject code into the first/target exe so that it runs the second exe first and then itself. So the final output after the injection should look something like this: "Injection worked. Injection didn't work!". My idea was to use OllyDBG. I opened the target exe and I added the following code into the code cave at the end of the code:

ASCII "inject.exe"
PUSH 1
PUSH 008B1F7C               (Address of ASCII "inject.exe")
Call WinExec
Call __security_init_cookie (This is the assembly code at the entrypoint which I overwrote with a JMP instruction to this codecave)
JMP 008B1572 (JMP back to next instruction after entrypoint)

And the entrypoint looks like this:

JMP 008B1F87 (JMP to codecave)

This code should execute inject.exe which is the second exe I made (and this exe is located in the same folder as the target exe). When I run this in OllyDBG it works and it gives me the desired output but as soon as I save it to an exe (Copy to exectuable -> All modifications -> Copy All -> Save as InjectionTestPatched.exe) it won't run anymore and crashes before printing anything. I also checked the %errorlevel% after execution which was -1073741819 and not 0. I don't really understand why the code worked in OllyDBG but not when I save it as an exe.

Does someone know what is going on here? (Please excuse my bad English as I'm not a native english speaker)

EDIT: I think I figured out WHY it is behaving like this but I don't know how to fix it. When I debug the Patched EXE every address seems to be correct but the address to the ASCII isn't. all JMP/CALL addresses adjust accordingly to the offset but the address to the ASCII remains static (the PUSH 008B1F7C doesnt change). Could ASLR be the source of my problems? And if yes, how can I bypass this...

OllyDBG

Here the address in red should point to the ASCII but it is the same as it was before (the addresses changed after the exe was made). What I don't understand is that the JMP address changed to the right address but the PUSH not. Why does that happen, how can I fix this? (EDIT2: Problem solved)

EDIT2: So I figured out a way to push the ASCII address on the stack correctly everytime by loading the EIP into EAX and sub it. This seems to work beacause the ASCII address is always on the stack when I reload the code. But now I have the next problem which is that WinExec doesnt seem to work anymore after reloading. OllyDBG doesn't even recoginze this instruction anymore as it shows it as 4 individual DB lines and not as CALL WinExec. How could I solve this?

EDIT3: PROBLEM SOLVED! the Call for WinExec seemed to have been changed due to ASLR even tho the address is always the same. I solved it by loading the static address to EAX and then with a CALL EAX i can call a static address which is not affected by ASLR. My Injection worked now.

4
  • Without much looking into the issue I think the common solution to such is call after the string + pop. May 18, 2020 at 10:52
  • Why pop and call after the string? The original problem was that i "hard-coded" the address of the ASCII for the PUSH. the Problem with that is that ASLR changes the address of the ASCII and thus the PUSH becomes invalid. As I said the workaround was to write code that calculated the ASCII address relatively. I did it by getting the current address (EIP) and subtracting 10h of it to get the address of the ASCII. This worked beautifully
    – skudo
    May 18, 2020 at 10:55
  • when you call, an address of the next instruction is pushed on the stack for the ret opcode. In your case it would be a string and thus by pop-ing you could obtain the address of it. May 18, 2020 at 10:58
  • Oh thats what you mean.Yes thats exactly what I did. I just didn't know that this was possible as I was still pretty confused by the ASLR.
    – skudo
    May 18, 2020 at 11:00

1 Answer 1

3

So I finally solved my problem. Here a quick explanation on how I did it:

The original problem was that I used "fixed" addresses for the PUSH meaning that it pushes always the same address (which should be the address of the ASCII). But ASLR randomizes the base address upon creating the EXE which means that the address becomes invalid as it points now to a totally different place than before. The workaround was to determine the address more "relatively" rather than absolute.

The main idea was to somehow get the current address (EIP) and subtract a specific number from it so that now it points to the ASCII. This is possible by creating a function which is called. Every time a CALL is executed the address of the next instruction will be pushed on the stack. In this function the address is saved in EAX with POP and later pushed back so that the RET still knows where to return.

I added a CALL after the string to retrieve the address and subtracted 10h from it. Now I had the address of the ASCII in EAX then follows the same code as before where WinExec is called only with the difference that now EAX is pushed onto the stack rather than the "absolute" address. Before calling WinExec I saved the address of WinExec in EAX (because the address for WinExec stays the same even with ASLR and the problem with ASLR is that the Address is going to modified and thus it won't corresponding to WinExec anymore). Then I just made a CALL EAX to run WinExec and the rest is the same.

Here is the full code:

Entrypoint: JMP <address of the first CALL in injected code>

POP EAX                               (Puts address of next instruction into EAX)
PUSH EAX                              (Copies address back to the stack so that RET knows where to go)
RET

ASCII "inject.exe"
CALL <address of the routine above>   (puts address of next instruction into EAX)
SUB EAX,0x10                          (SUB EAX,<this number depends on the size of the executable name. Just subtract the address of this instruction with the address of the ASCII>)
PUSH 1
PUSH EAX
PUSH WinExec                          (Puts address of WinExec onto stack so that the address won't change because of ASLR)
POP EAX
CALL EAX                              (execute WinExec)
CALL __security_init_cookie           (replace this instruction with the instruction that will be overwritten by the JMP instruction to this code cave. In my case it's this call)
JMP <address of second Instruction at Entrypoint>
5
  • well then it's not an answer to your question and as such should be removed. Please consider writing an actual answer for the sake of future seekers ;) May 18, 2020 at 10:50
  • 1
    Well I kind of explained it briefly in my original post but I suppose I'll include a more detailed version in my answer then.
    – skudo
    May 18, 2020 at 10:52
  • 1
    I made a more detailed explanation. I hope it's understandable as I have trouble explaining things in english...
    – skudo
    May 18, 2020 at 11:15
  • 1
    @skudo thanks. If you could also replace the image by the textual version, that would be brilliant. Thanks in advance.
    – 0xC0000022L
    May 18, 2020 at 14:51
  • I also included some comments to explain the code a bit better. Is this ok or should I remove them?
    – skudo
    May 18, 2020 at 15:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.