Jump to content


- - - - -

VitualAlloc problem.


  • Please log in to reply
34 replies to this topic

#31 keng

keng

    Tamed

  • Full Members
  • PipPipPip
  • 33 posts

Posted 30 December 2011 - 09:04 AM

But Veggy, if you'll yse a timer there will be a small possibility that the image base will get realoaded and old cave jump will be fired between the timer ticks and you'll jump to an old offset -> get a crash. I believe that it's better to make a cave in the spot when the game calls the necessary dll's function and calculate the image base before the actual call if the trainer's option bound to that function is active (it can be easily checked with a flag).

#32 Veggy

Veggy

    Tamed

  • Full Members
  • PipPipPip
  • 32 posts

Posted 30 December 2011 - 02:28 PM

Keng,

You're right, BUT this occasion barely happens. The timer is executed every couple milliseconds to read the imagebase and write offsets in the code.
Since you're using a DLL you could make an staticly created DLL, dynamic dll would work just fine aswell just needs a little bit more code. I am still using a Staticly generated DLL just for simplicity sake.
In your DLL you stick that timer which keeps reading the module base of the DLL you are applying your cheats to.
Than when you jump, jump to the STATICLY generated dll, Therefor I never came across any problems your jump to a so called codecave will always be working. The thing to get back to the gamecode is rather easy.
I prefer to use push/ ret.
So in your cave you use something like:

HealthCave:
mov dword ptr [eax+400h], 42c80000h
push [HealthRet]
ret

And you update HealthRet with that Timer aswell.
HealthRet will hold the return address you calculate by taking the Imagebase of the module and adding the offset to it to get the function address.
Since the timer is executed each millisecond in a seperate thread you won't experience any crashing.
I have yet to find a game in all those years I hacked games which crashes when doing it this way.

#33 genuine

genuine

    Rookie

  • Administrator
  • 97 posts

Posted 05 January 2012 - 08:56 PM

Interesting thread here, pertaining to the dlls being reloaded with every new map load, I have never encountered this back in the past, but it did come up just after i stopped hacking and i did give it some thought, so here are my thoughts on it.
I see it like this, if there is some function going on in a game which causes something like this to happen, then the logic is of course in the game somewhere. The first place i thought to look was the place where the game is loading the game files for the next level. I havent thought of how to find this place in the code but with some IDA skills and knowledge of the game engine ( or library the game uses if any ) i think it would be rather easy, then to trace the code and find where its doing the re positioning of the games modules..
But i do find it strange that game developer would do this, then when i think about it, its us hackers who cause them to do such strange things :P. Anyways good luck

#34 keng

keng

    Tamed

  • Full Members
  • PipPipPip
  • 33 posts

Posted 06 March 2012 - 04:56 AM

Hello again, everybody!

I've lost all my source code due to hardware crash, by this time I've already rewritten 90% of it, but there is one small problem. I'll try to explain. I've got something like this code:


.data?
option_buffer dd ?

.code

start:
invoke InitOption,addr option_buffer
invoke ExitProcess,0


InitOption proc buffer:dword

mov byte ptr [buffer],0FFh
mov byte ptr [buffer+1],0FFh
ret

InitOption endp

I'll try to explain - there is a buffer-variable for every trainer option. There is also a function named InitTrainer, that creates all the cave-codes - it gets all needed stuff for option, gets the address of the original game's instruction of the option (aF), allocates some memory for cave (aT), then calculates the buffer as I've shown earlier ("call aT nop nop"). The bytes in the brackets must then be written to the instruction's address (aF) like this:

(aF)
0x1234567: original instruction (7 bytes long, for example)

poke!

(aF)
0x1234567: call cavecode nop nop (1 byte for call, 4 for address, 2 nop's)

(allocated, aT)
cavecode: cave bytecode + ret

So when the trainer is activated I create all the caves and write all the buffers for each option, then when some option's key is pressed I just write it's buffer (where "call cave nop nop" is stored) to game's instruction (aF) for toggle on and original_bytecode for toggle off.

The problem is in the WriteBuffer instruction - it get's the address of the option's empty buffer as agrument (invoke WriteBuffer,addr opt_buffer), and after it worked nothing happens - buffer is just empty.

The somekind of solution looks like this:


TestProc PROTO :DWORD

.data
hInstance dd ?
testparam dd 0

.code
start:
invoke GetModuleHandle,0
mov hInstance,eax
invoke TestProc,addr testparam
invoke ExitProcess,0

TestProc proc ff:DWORD

mov eax,[ff]
mov dword ptr [eax],-1
ret

TestProc endp

end start

But the buffer may be longer than 4 bytes (eax) and I think that this looks like a hack. So the problem is - to write some bytes (5-10) to the variable which the function gets as an argument.

Any ideas? :)

#35 keng

keng

    Tamed

  • Full Members
  • PipPipPip
  • 33 posts

Posted 10 March 2012 - 08:43 PM

Small up - I solved the problem. Code (MASM syntax):

WriteBuffer proc at:DWORD,af:DWORD,buffer:DWORD,bsize:DWORD


push eax ;Save needed registers
push ebx
mov ebx,[buffer] ;Move buffer address to ebx
mov dword ptr [ebx],0E8h ;Write call opcode to ebx
mov eax,at ;Move cave address to eax
sub eax,af ;Substract game address from it
sub eax,5 ;Substract 5 more bytes - 1 for call opcode and 4 - for address. Now we've got needed bytes in reversed order
mov byte ptr [ebx+1],al ;Write first byte of address
mov byte ptr [ebx+2],ah ;Second one
shr eax,16 ;Move 16 bits right
mov byte ptr [ebx+3],al ;Write third byte
mov byte ptr [ebx+4],ah ;Fourth
mov eax,bsize ;Now - calculate if any nop's needed. Get size of game's instruction length.
sub eax,5 ;Substract 5 from it (1 for call etc.)
cmp eax,0 ;No nops needed?
je $+10 ;If so - get out
mov byte ptr [ebx+5],090h ;Else - write a nop opcode
inc ebx ;Increase buffer's pointer address (not value!)
dec eax ;Decrease rest amount of nop's needed
jne $-11 ;Since eax is still zero after the comparison - get back to cycle
pop ebx ;Restore used registers
pop eax
ret ;End


WriteBuffer endp

Usage is rather simple:

.data
buffer dd 0
at dd 0
af dd 0

.code
invoke WriteBuffer,at,af,addr buffer

That's it. :)



Affiliates: 
Follow us on:

Stay Safe: Read this info about dVT official outbound links!