View Full Version : Help with a codecave, imports
abitofboth
March 25th, 2009, 06:30
So, i am trying to inject some meaningful code into this application, basicly i want to write some stuff to a file and then have the program carry on on its business.
So i wrote a little something that appended to a file in C and stole the code with olly.
So far so good.
Now I try to recreate this code in my cave, again with olly(this goes into a loader at a later point) and right there im at a loss again.
This is what i am stealing from.
8B3D A4204000 MOV EDI,DWORD PTR DS:[<&MSVCR90.fwrite>]
A little call to fwrite, should not be a problem right?
Now it seems once injected;
FF15 AC204000 is just that ; CALL DWORD PTR DS:[4020AC]
We're not resolving the correct MSVCR90.fwrite address anymore .. I guess i could have told my self that these things must be dynamic in nature!
So really, my question is, what do I do from here?
Do i find the 'new' address of fwrite(if at all imported by the code i want to patch)
Do i write-to-file in another manner? (old dos way perhaps, int 21)
This is my stuff, feel free to critque;
705077AA MOV ECX,DWORD PTR SS:[ESP+4] ; recreation of code molested by jmp overwrite
705077AE PUSH ESI ; recreation of code molested by jmp overwrite
705077AF JMP 70501BA3 ; tmp patch, nopping when i want to active rest of code.
705077B4 PUSH EAX ; saving state
705077B5 PUSH EBX
705077B6 PUSH ECX
705077B7 PUSH EDX
705077B8 PUSH ESP
705077B9 PUSH EBP
705077BA PUSH EDI
705077BB NOP
705077BC PUSH 403FE8
705077C1 PUSH 403FC8 ; ASCII "c:\file.txt"
705077C6 CALL DWORD PTR DS:[4020AC] ; FIRST ERROR ADDRESS IS NOT REACHABLE.
705077CC MOV ESI,EAX
705077CE MOV EAX,ECX
705077D0 NOP
705077D1 NOP
705077D2 ADD ESP,10
705077D5 LEA EDX,DWORD PTR DS:[EAX+2]
705077D8 MOV CX,WORD PTR DS:[EAX]
705077DB ADD EAX,2
705077DE TEST CX,CX
705077E1 JNZ SHORT 705077D8
705077E3 MOV EDI,DWORD PTR DS:[<&ole32.OleUniniti>; ole32.OleUninitialize
705077E9 SUB EAX,EDX
705077EB PUSH ESI
705077EC SAR EAX,1
705077EE PUSH EAX ; <&ole32.OleUninitialize>
705077EF LEA ECX,DWORD PTR SS:[ESP+10]
705077F3 PUSH 2
705077F5 PUSH ECX
705077F6 CALL EDI
705077F8 PUSH ESI
705077F9 PUSH 2
705077FB PUSH 1
705077FD PUSH 40211C
70507802 CALL EDI
70507804 PUSH ESI
70507805 CALL DWORD PTR DS:[4020A0] ; another fcked function call
7050780B NOP
70507812 NOP
70507813 POP EDI ; right amount of pops not determined yet
70507814 POP EBP
70507815 POP ESP
70507816 POP EDX
70507817 POP ECX
70507818 POP EBX
70507819 POP EAX
7050781A NOP
7050782E NOP
7050782F JMP 70501BA3 ; JMP back from cave
abitofboth
March 25th, 2009, 07:30
I found what seems to be the 'right' addresses, olly now assembles the calls like this
705077C6 FF15 10F0C377 CALL DWORD PTR DS:[msvcrt.fopen]
But i still get this "Dont know how to step because memory address at 8B55FF8B is not readable, try to change eip..."
Where 8B55FF8B comes from i have NO idea...
abitofboth
March 25th, 2009, 10:05
I've also shifted memory locations of the arguments pushed yo the function to be within the same module, still no dice... starting to get on my nerves here.
wtbw
March 25th, 2009, 10:06
8B FF MOV EDI, EDI
55 PUSH EBP
8B..
Looks like you're a level of indirection off, and trying to jump to an address which is actually the code at the start of the function :-)
fr33ke
March 25th, 2009, 10:07
Read http://woodmann.com/fravia/lazcalc.htm , everything is explained.
abitofboth
March 25th, 2009, 10:27
edit : sorry didnt see your replies .. looking it up now
Looking in Olly i see this memory structure
address - PE Header
address - code
address - imports, exports
address - data
address - resources
address - relocations
So im looking through the code and find other calls to MSVCRT and wow, these look something like this
FF15 9C805070 CALL DWORD PTR DS:[<&MSVCR71.ceil>]
And sure enough, 9C805070 (reverse) is right in the "imports, export" segment, and the adress contains, tada, a pointer to the actual function is msvcrt..
So .. why is it so wrong of me to just use the real function pointer instead of going via &import-address?? I dont get it .. is the only way to call a function outside of my own body via the import segment??
.. and more to the point, how do i get around this??
abitofboth
March 25th, 2009, 11:38
wtbw - > yes, you're right 8B55FF8B does indeed look alot like the beginning of fopen in msvcrt

... I realize this must be a very stupid question, but what is wrong with that? A 'level of indirection off? Does this mean that the code have to 'import' the function for me to properly call it? (like i try to describe in my post above)
Darren
March 25th, 2009, 12:20
Hi abitofboth,
What about forgetting about the cave and making a loader and injecting a dll perhaps, once hooked you can do as you wish in the dll and use any API / functions you so choose, http://www.madshi.net/ has a nice hook tool set, far as i remember the whole lib is free to download and use, you only pay if you want the source code, has nice examples as well, you can hook code or hook APIs, with what was said above, you need to find the correct IAT entry for the functions you want to use, if they are imported then use a CALL DWORD PTR DS:[IAT ENTRY Of API] , you could find in Olly or a PE Editor such as lordpe
IAT = Import Address Table
Darren
naides
March 25th, 2009, 19:06
Quote:
[Originally Posted by abitofboth;79839]
FF15 9C805070 CALL DWORD PTR DS:[<&MSVCR71.ceil>]
What is wrong with this? you ask This indirect call expects A POINTER to the right function in between the brackets. Remember that a pointer is an address that contains another address, but what does the program find? The actual FIRST 4 BYTES of fopen, now tries to jump to that nonesense address, and bang, the program crashes. What you need to place in those brackets is the entry corresponding to fopen in your IAT.
Another NOT GOOD solution would be to code a CALL 7050809C instead of CALL DWORD PTR. What is the draw back? this hardcoded address only corresponds to fopen in your system, perhaps only in this current run, because you would screw up the whole concept of Dynamic Link Library
And sure enough, 9C805070 (reverse) is right in the "imports, export" segment, and the adress contains, tada, a pointer to the actual function is msvcrt..
So .. why is it so wrong of me to just use the real function pointer instead of going via &import-address?? I dont get it .. is the only way to call a function outside of my own body via the import segment??
.. and more to the point, how do i get around this?? |
In Blue
abitofboth
March 25th, 2009, 19:53
Darren -> Thanks but i've allready been down that road with detours and the i cannot find what i am looking for via the std win32 apis.
naides -> Thanks alot, this was indeed my issue and the other NOT GOOD idea is actually what i have going now (wich is somewhat working). The bugger is this, i am pretty sure the IAT does not contain a value for fopen/fwrite/fclose

.
Well, now i DO get stuff written in my file so theres progress non the less.
Its still messed up though, but thats my lacking asm skills more than anything else! Seems i got quite a few things to learn here as well!
naides
March 25th, 2009, 21:45
@abitofboth: There are viable solutions to your problem: fopen/fwrite/fclose are good old C functions, that a program written in any of the new languages will seldom invoke/import. But I would look at the functions that your original program do import. I would bet it uses win32 APIs such as CreateFileA for fopen, ReadFileA and WriteFileA. The functions will require slightly different parameters so you need to learn them and how the parameters are passed to the stack regarding the calling convention, all of which is in the win32 API reference.
Also, the shortcut you took of compiling your injected code in C is what is giving you trouble. Perhaps if you compiled it with a C++ utility may save you some headaches.
Darren
March 25th, 2009, 22:17
Hi again,
dunno if you missed my point, what i meant was you could hook the code to jump to your dll and you can do what ever you like with the data/information in your dll, as you will have the entire win api and c runtime at your disposal and avoid the problems of pasting in stuff via olly and fixing up addresses and such, i did check on mad hook, seems its not free to public as it once was, due to misuse

but i did see it was around on exetools forums, if that helps you any, perhaps if you could explain in a little more in detail what your trying to achieve, maybe more help could be provided
Good Luck
Darren
abitofboth
March 26th, 2009, 05:27
naides -> thats solid advice, thanks, ill look into using those api's .. as it turns out, the way fwrite wants things allocated on the stack is really not too newbie-trivial and yes i have had a nagging suspicion that it is this c-compile-steal shortcut is causing more trouble(but i am having soooo many maybe's in my head right now and i cant act on all of them) than its worth(allthough not in the api-regard) so your point is right on.
Darren -> Actually that point did elude me

Sorry, it was late last night and a tired brain is not the sharpest tool when it comes to juggling these things.
It is defnetly worth a shot, but not right now .. I've invested quite some time in making this work and coming this far with my own cave (+fileoutput) and quite frankly its just more satisfying messing with opcodes on this level rather than someone elses highlevel abstraction framework to do the same.. easier? maybe ... but is it as *fun*

.
And i still remember the kinks in making detours working in the first place, just because its highlevel does not mean it's not associated with trouble. Just on another level perhaps

.
You have all been very very helpful .. great community!
abitofboth
March 26th, 2009, 07:04
is it OK to express a little enthusiasm? allthough its not writing quite a comprehensible string yet...
.... The cave is working ... The application is humming away and my file is getting fatter and fatter ... fatter and fatter as we speak, i can smell victory in the air! this is a good day to cave haha...
FrankRizzo
March 26th, 2009, 13:30
If I had to guess, I'd say that you're calling the function correctly now, but that your parameters pushed on the stack a wrong with regards to the buffer that you write. Thus, it's just writing out something random, and not the data that you intend.
Sorry if you already knew that, but just in case you didn't, that's my thought!
abitofboth
March 26th, 2009, 17:19
Frank - Indeed it was, i messed up my ecx on the way, its all fixed now and im logging everything i need to a local file on my harddrive.
It is working! Oh the nice smell of victory ..mmmm.. couldnt have done it without you guys!
Next step is making a patcher in C# that injects the target process via writeprocessmemory with my lovely opcodes



Powered by vBulletin® Version 4.2.2 Copyright © 2018 vBulletin Solutions, Inc. All rights reserved.