View previous topic :: View next topic |
Author |
Message |
capi SF Senior Mod
Joined: 21 Sep 2003 Posts: 16777097 Location: Portugal
|
Posted: Tue Nov 23, 2004 9:26 pm Post subject: |
|
|
Nope, sorry, don't have MSN.
You need to make the jmp to the actual address, not to [address]. Say if the allocated address is 80123456, you need to jmp 80123456.
For example, if the address is in register eax, you need to jmp eax, not jmp [eax].
What parameters does the access violation give you? It should say something like "the instruction at address blah tried to access memory at address bloh" - that should give you a hint as to what is going on. See the target address, if it's the right one. See what instruction caused the access violation.
|
|
Back to top |
|
|
nildo Just Arrived
Joined: 19 Nov 2004 Posts: 0 Location: Brazil - São Paulo
|
Posted: Wed Nov 24, 2004 1:31 pm Post subject: |
|
|
I only receive this Access violation:
Quote: |
Access violation at address 195570AE. Read of address 195570AE |
At this address doesn't have nothing. Only many "???".
I can not understand why, because every different JMP that I try, I get the same access violation with the same kind of address.
Maybe I can try to "patch" a JMP writing directly it's OPCODE and executing it. Do you know the Opcode for a FAR jmp, and if it need to be Relative or Absolute?
Important: If I change the EIP to the new location, and try to execute, I get an error too. Like if I'm not able to execute the code in that arena.
Or, a better idea... Using all those stuff of VxdCall, is there a way to alocate memory inside another process address space (unser 9x)? If so, all my problems are gonne...
Thank you!
|
|
Back to top |
|
|
capi SF Senior Mod
Joined: 21 Sep 2003 Posts: 16777097 Location: Portugal
|
Posted: Wed Nov 24, 2004 5:38 pm Post subject: |
|
|
The opcode for a relative JMP, displacement relative to the next instruction, is 0xE9. This is what you'd use if you want to hardcode the address in:
for example, say your target is at address 80100050, and that the JMP instruction starts at 00402000. This is what you'd want to have:
Code: |
address - data
00402000 - E9 4B E0 CF 7F jmp 80100050 |
Note that the offset is in small endian notation (as is the case in x86 platforms). How did we calculate the offset? We took the target address, 80100050, and subtracted the address of the instruction immediatly after the JMP. As we know the JMP is 5 bytes in length, since it's starting at address 00402000, the next instruction is at 00402005. Thus, the desired offset is 80100050 - 00402000 = 7FCFE04B. Just store that DWORD right after the E) opcode - you should not have to do any byte shifting as it will already be in small endian form inside the integer variable. So, in short:
Code: |
offset = target_addr - (address_of_jmp + 5) |
Store that right after the E9.
As always make sure with the debugger, check that everything is in memory as it should.
As for what you're seeing with the access violation, that address does not seem to have anything to do with what you want. You should be jumping to somewhere above 80000000. Are you sure the JMP is going to the correct address? You also said that if you manually edit EIP to the correct address, you get an error. Is it the same error? When do you get the error? Right now I'm suspecting the problem may be with the code you're trying to execute... That address you quoted has nothing to do with shared space, either the JMP is jumping somewhere it shouldn't, or the code you injected is buggy. Have you done a step by step with the debugger until the JMP, and after it, to see exactly in which instruction it goes wrong? Same thing changing EIP, exactly when does it error out? Immediatly before executing your instructions? During their execution? Have you checked that the instructions at the starting address are what they should be?
|
|
Back to top |
|
|
capi SF Senior Mod
Joined: 21 Sep 2003 Posts: 16777097 Location: Portugal
|
Posted: Wed Nov 24, 2004 10:37 pm Post subject: |
|
|
Ok, I just got your code by email, and have debugged it.
As I expected, there is absolutely nothing wrong with what we've been looking at. The memory is being allocated correctly, the JMP is going to the correct place. And... the code you injected is being executed.
The access violation is not happening right before executing the first instruction, as you indicated. In fact, the access violation is being caused by the code you injected. In particular:
Code: |
var
newProc: array [1..34] of Byte = (
$83, $C4, $F4, // ADD ESP,-0C
$89, $0C, $24, // MOV DWORD PTR SS:[ESP],ECX
$89, $54, $24, $04, // MOV DWORD PTR SS:[ESP+4],EDX
$89, $44, $24, $08, // MOV DWORD PTR SS:[ESP+8],EAX
$8B, $C4, // MOV EAX,ESP
$50, // PUSH EAX lParam
$51, // PUSH ECX wParam
$6A, $4A, // PUSH WM_COPYDATA [$4a] Message = WM_COPYDATA
$68, $90, $90, $90, $90, // PUSH [HandleDoForm] [Handle DO FORM]
$E8, $90, $90, $90, $90, // CALL [user32.SendMessageA] SendMessageA
$83, $C4, $0C, // ADD ESP,0C
$C3 ); // RETN
|
The access violation is happening at that CALL instruction. You must remember that call is relative, you must fill in that offset correctly, just as I told you to do for the E9 JMP in my previous post. That's your problem right there, the code injection is happening perfectly as it should. It's the code that you're injecting that's failing.
You need to fill in that offset after the E8 (the part that reads 90909090 in the above) with the correct relative offset to the SendMessageA API. My suggestion is that you use GetProcAddress to obtain the address of SendMessageA, then use the formula I quoted in my previous post to obtain the offset. You will obviously need to calculate the offset at runtime, and it will depend on the base address of the allocated region. Thus, after you've allocated shared memory, you need to do the following:
Code: |
offset = address_of_sendmessage - (base_address + 30) |
Where base_address is the base of the shared memory you allocated, and the + 30 comes from just counting the bytes in your code until reaching the instruction after the CALL. You need to place that offset at the address (base_address+26), so that it occupies the 4 bytes right after the E8.
This is all partially because (as you may or may not already know), when you issue a CALL SendMessage in your code, the compiler won't actually hardcode the SendMessage address in there. It will instead rely on something called the Import Address Table, which is a part of the file that's filled out with the addresses at runtime by the PE loader. Furthermore, even if it did hardcode the address to SendMessage (which would be a very stupid thing to do portability wise, as different versions of USER32.DLL may have the function at different addresses), your code would still not work, as that is a relative call. Meaning if you move the CALL around in memory (as you have to in order to put it in shared space), the call will no longer work. Your solution is to do as I explained above, obtain the address at runtime by GetProcAddress, then calculate the offset from the instruction immediatly after the CALL (already in the shared space, obviously).
Also, looking at the code, I strongly suspect that push [HandleDoForm] isn't going to do what you want it to do. Opcode 68h is a push imm32, meaning it will push an immediate operand, taken from the dword following it (in this case, the 0x90909090). Unless you actually want to put 0x90909090 in the stack (which I very much doubt), you'll have to change that as well. Remember that this code, if it is to be executed by other processes, needs to have everything it needs right there, there can be no references to external stuff depending on IATs, or even worse, static variables belonging to your own process (as the others won't be able to see them, obviously, and will instead read some garbage from their own address space). Now, I assume the handle to the window will remain constant in your case, unless you want to have multiple instances of the window or something like that. So, what you need to, at runtime, is take the value of that HandleDoForm that you want to push, and write it into the injected code, immediatly after that 68h byte. So, if HandleDoForm was 760h, you would have 68 60 07 00 00, which is push 760h. So there's another thing you'll be needing to patch in your injection code at runtime, before injecting it.
By the way, one additional note: there is no need to use WriteProcessMemory to write to shared space (or in fact, to write to anywhere within your own process' context). That means, no need to call GetCurrentProcessId and then OpenProcess to open your own process. You can just fill in the shared space as you would fill in any other array, the very fact that it is in shared space means it will be directly accessible without having to change context.
And well, I think you should be all set by now
|
|
Back to top |
|
|
nildo Just Arrived
Joined: 19 Nov 2004 Posts: 0 Location: Brazil - São Paulo
|
Posted: Tue Dec 07, 2004 4:44 pm Post subject: |
|
|
Capi, I got another problem.. I dunno if you will be able to help me, but I really need this. I'll describe the problem:
I was able to get write access into the shared area. Since here OK. But only works if I try to change something from my own process. For example:
Code: |
GetProcessMemory( GetModuleHandle( 'user32.dll' ), 'MessageBoxW' ); |
Then If I write into this area it works. But I need to change the same address, but into the context of another process. NOTEPAD.EXE for example, and I am not able to write. Returns no error but nothing get written there.
I'm using this to write:
Code: |
WriteProcessMemory( TheNotepadHandle, MsgBoxW_BaseAddress, @JmpCode, JmpSize, Anything ); |
returns no error but nothing get written there. See that I'm using the Notepad Handle. If I write it from the context of my own process it works.
Any idea?
|
|
Back to top |
|
|
capi SF Senior Mod
Joined: 21 Sep 2003 Posts: 16777097 Location: Portugal
|
Posted: Tue Dec 07, 2004 5:10 pm Post subject: |
|
|
If you are writing to the shared area then the change will be effective for all processes.
In particular, if you alter the MessageBox API code in the USER32.DLL space, then it will be altered for all processes, as USER32.DLL is mapped in shared space for all processes. That is, the same physical pages are mapped to all processes.
There is no need to use WriteProcessMemory to hook APIs in Windows 9x through this method, that's the whole point of gaining write access to shared space. It may or may not work with WriteProcessMemory, and is an added variable unnecessarily.
Now, if you are having problems getting the hook to work on other processes, either you are not writing to shared memory, or the injected code is bugged. I would suggest you take the debugger (SoftICE being my recommendation) and step through the whole process to find out where the problem is.
|
|
Back to top |
|
|
nildo Just Arrived
Joined: 19 Nov 2004 Posts: 0 Location: Brazil - São Paulo
|
Posted: Thu Jan 20, 2005 8:55 pm Post subject: |
|
|
Hello again Capi!
Do you know if theres a VxdCall or some trick that creates a remote thread, under win9x?
Thank you!
|
|
Back to top |
|
|
newman Just Arrived
Joined: 01 Aug 2005 Posts: 0
|
Posted: Wed Aug 03, 2005 8:25 am Post subject: |
|
|
hi capi,
I changed memory page Permissions of kernel32.dll with PageModifyPermissions,but I can't restore,why?
push 00040000h
push 0
push 1
push startpage
push 0001000Dh
call [vxdcall]
return eax=ffffffff
|
|
Back to top |
|
|
capi SF Senior Mod
Joined: 21 Sep 2003 Posts: 16777097 Location: Portugal
|
Posted: Wed Aug 03, 2005 2:38 pm Post subject: |
|
|
Hi newman,
You're not including the PC_STATIC flag in the permissions, which is required to change the permissions of system memory (that is, addresses above 2GB).
For more details, you might like to read a previous post on this same thread, where I ellaborated somewhat on hooking Windows 98 APIs.
|
|
Back to top |
|
|
newman Just Arrived
Joined: 01 Aug 2005 Posts: 0
|
Posted: Mon Aug 08, 2005 4:56 am Post subject: |
|
|
hi capi,
thanks very much!
how do you do with hook chains of same api?can you give me hint ?
thanks very much again.
Last edited by newman on Mon Aug 08, 2005 6:36 am; edited 1 time in total |
|
Back to top |
|
|
|