Hello, I want to enhance a very old win32 program whose source code got lost long ago. I searched and found an adequate place inside a DLL this program is using. What I wanted to do now is placing a codecave into there that basically just loads and executes a function placed inside another DLL I created before.
Here is the crux I am facing: My codecave is somewhere in the empty part of the .text section. But now I don't know either the DLL module's base address or the base address of kernel32.dll where I can find LoadLibraryW. My goal is doing something like this:
OriginalDLLSection:
...
; some DLL code, blabla
MOV EDX, 0xDEADBEEF ; some uncertain handle value from the DLL gets stored, I need that in my own DLL
JMP CodeCaveSection ; <---- replaced some old, unneeded opcode with that injection of my codecave
POP EDI ; first opcode after my codecave, let it have symbolic address <ReturnAddressToOriginalDLLCode> now
; some more code, blabla
...
; Later on, at the end of the .text section, my codecave:
my_dll DB "my_custom_module.dll"
my_func DB "my_function" ; void my_function(DWORD)
...
CodeCaveSection:
; prepare LoadLibrary
PUSH my_dll ; problem: In OllyDbg, I must know the address where the DLL filename string is stored.
CALL <kernel32.LoadLibraryA> ; problem: I don't know the base address of kernel32 either
CMP EAX, 0 ; if loading failed...
JNZ <ReturnAddressToOriginalDLLCode> ; same problem as in push
PUSH EAX ; push the module handle
PUSH my_func
CALL <kernel32.GetProcAddressA>
CMP EAX, 0 ; function not found...
JNZ <ReturnAddressToOriginalDLLCode> ; back to original code, do nothin
PUSH EDX ; push the 0xDEADBEEF from above as the function argument of my_function
CALL EAX ; call my DLL function
JMP <ReturnAddressToOriginalDLLCode>
What I thought of was getting the return address of the original function from the stack and perform an AND with FFFF0000 to get the base address and add relative offsets (which I can read out of my debugger), so I can at least address my strings inside the codecave. But what about LoadLibrary and GetProcAddress? I heard I could find the base address of kernel32.dll inside the Import Address Table, but no idea how.
Sorry if my questions sound kind of dumb, I am not very into such low-level issues. I hope you understand my problem.
SucodoJ
SucodoJ,
did you read the forum rules (http://masm32.com/board/index.php?topic=4.0), especially rule #3? If not, you should do it immediately. What is a codecave? An unused block of memory that someone, typically a software cracker, can use to inject custom programming code to modify the behavior of a program.
Gunther
I haven't since the rules are the same everywhere anyway. Now I am just confirmed.
No need to tell me; I know what a codecave is.
I said it's about a piece of very old software that is neither sold or even published, it has been only developed for one purpose and it's about me to either enhance it with some features or abandon it completely which we really wouldn't like to do.
no need to re-write the entire program
just re-write the DLL from scratch and modify the source code to suit your needs
we're not allowed to help people reverse-engineer code
Dave,
thank you. You've underlined my point. :t
Gunther
Microsoft has a library that may be of use to you. Detours (http://research.microsoft.com/en-us/projects/detours/) which will eliminate the need for code caves. I have seen its use in the baldurs gate series of games - the Throne of Bhaal Extender project (ToBEx) uses this (http://www.shsforums.net/forum/606-tobex/) which allows for overriding hard coded limitations of the game engine and fixes bugs and other issues. The detours allows you to override an old function and 'trampoline' to a new function without the need for the codecave method. So might be worth a looksee. Hopefully that may help you.
And code caves are a pain in the "Hintern". :t
Andy
Another option is to create a new DLL that 'passes on' some functions but fakes others. Here is an example that uses one CRT function and fakes a second one (always assuming that your fairy tale about old code and lost sources is correct ;)):
include masm32rt_nocrt.inc
.data?
hMs dd ? ; handle for MSVCRT dll
pPrint dd ? ; address of printf
.data
tx1 db "msvcrt.dll", 0
tx2 db "printf", 0
.code
LibMain proc instance:DWORD, reason:DWORD, unused:DWORD
.if reason==DLL_PROCESS_ATTACH
invoke LoadLibrary, offset tx1 ; chr$("msvcrt.dll")
mov hMs, eax
invoke GetProcAddress, hMs, offset tx2 ; "printf"
mov pPrint, eax
.elseif reason==DLL_PROCESS_DETACH
invoke FreeLibrary, hMs
.endif
mov eax, TRUE
ret
LibMain endp
printf proc C args:VARARG ; $export
push [ebp+16] ; ####### caution - this fake printf expects always three args,
push [ebp+12] ; i.e. format, one string, one integer ##########
push [ebp+8]
call pPrint ; this calls the 'real' CRT printf
add esp, 3*DWORD
ret
printf endp
strlen proc pStr ; $export
mov eax, pStr
dec eax
.Repeat ; slow but for a demo it's OK
inc eax
.Until !byte ptr [eax]
sub eax, pStr
add eax, 1000 ; just to demonstrate that it's not the real CRT strlen
ret
strlen endp
end LibMain