![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Programmer
Join Date: Dec 2005
Posts: 65
Rep Power: 3
![]() |
C/asm jmp calculation
Ok this is mostly C but my question is really based around ASM techniques so I decided it would be best to post it here.
I'm working on a small project that will overwrite parts of the machine code in the current process space. My goal is to always redirect the function a() to function b(). Not a very practical application but it's something to learn from ![]() Anyhow, here's the general code: byte patch[] = { 0xe9, 0x00, 0x00, 0x00, 0x00 };
void a() {
printf("a() called\n");
}
void b() {
printf("b() called\n");
}
int main() {
void* aptr = a;
printf("a: %p\n", a);
memcpy(patch+1, &aptr, 4);
printf("patching..\n");
memcpy(a, patch, sizeof(patch));
printf("patched\n");
printf("calling a()...\n");
a();
return 0;
}I cut out the part of the code that makes the memory space writable, so assume the memcpy() is legal. The array is a 5 byte jmp function I compiled and grabbed out of a disassembly. 0xe9 is the jmp, then 4 0x00's which is updated in the first memcpy() in main(). So everything works until I try to call a() at the bottom of main(), where it crashes. Is this pointer I copied into the function code valid? Why is it crashing? |
|
|
|
|
|
#2 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: elemental plane
Posts: 1,429
Rep Power: 5
![]() |
Variable 'a' is not declared so: void* aptr = a; will not point to somewhere undefined.
In your case, memcpy(a, patch, sizeof(patch)); makes it crash.
__________________
"Employ your time in improving yourself by other men's writings, so that you shall gain easily what others have labored hard for." -- Socrates |
|
|
|
|
|
#3 | |
|
Programmer
Join Date: Dec 2005
Posts: 65
Rep Power: 3
![]() |
Quote:
![]() The code ends up being in the array: 0xe9 0x04 0x03 0x02 0x01 assuming the address for the function a is 0x01020304 (little endian machine). |
|
|
|
|
|
|
#4 | |
|
Caffeinated Neural Net
![]() Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,033
Rep Power: 5
![]() |
Quote:
Why not try something like using double indirection to get at the memory pointed at by the function's offset, then changing the data there? Replace the function body with a RET instruction, or something. See if that works. [edit] No need for double indirection, my bad. I need sleep. [/edit]
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot. - Vaarsuvius, Order of the Stick Last edited by lectricpharaoh; Dec 15th, 2005 at 6:49 AM. |
|
|
|
|
|
|
#5 |
|
Caffeinated Neural Net
![]() Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,033
Rep Power: 5
![]() |
I tried this code, but I got an access violation for trying to write to the memory. I dunno how to make it writable in Windows (using DevC++/MinGW, so it might be similar to how you do it with gcc under Linux, if you care to share).
#include <stdio.h>
#include <stdlib.h>
void manlyMan(void);
void neuter(void (*soonToBeEunuch)(void));
void manlyMan(void)
{
puts("I am a manly man!");
}
void neuter(void (*soonToBeEunuch)(void))
{
char *target = (char *)soonToBeEunuch;
*target = 0xC3; // plain old RET (near)
}
int main(void)
{
puts("---");
manlyMan();
puts("---");
neuter(manlyMan);
manlyMan();
puts("---");
system("pause");
return 0;
}
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot. - Vaarsuvius, Order of the Stick Last edited by lectricpharaoh; Dec 15th, 2005 at 7:05 AM. |
|
|
|
|
|
#6 |
|
Newbie
Join Date: Nov 2005
Posts: 4
Rep Power: 0
![]() |
> Then, in the second memcpy(), you copy five bytes from patch to a four-byte,
> constant value. Assuming you have indeed made the function's offset address value > writable in the code segment, you're still trying to copy five bytes to a four-byte value > (oops). [...] What makes you think it is four bytes? He's changing the machine code of a() itself, not the symbol "a". "&a" is the same as "a" - the address of some code. And he is patching that code. void a() { printf("a() called\n"); Assuming push ebp, mov ebp, esp, push string, call printf, add esp, 4, pop ebp, we have at least six instructions occupying (much) more than four bytes. > byte patch[] = { 0xe9, 0x00, 0x00, 0x00, 0x00 }; You should be using some form of "call" instruction because a jump will not save the return address. Also, my opcode reference says 0xe9 is a relative jump, but you need an indirect one. The code you use should be the same as the code generated for void foo() { stuff } ... void (*p)() = foo; p(); Last edited by splyxx; Dec 15th, 2005 at 8:05 AM. |
|
|
|
|
|
#7 | ||
|
Programmer
Join Date: Dec 2005
Posts: 65
Rep Power: 3
![]() |
Quote:
http://research.microsoft.com/sn/detours/ Anyhow, I don't want to overwrite the opcodes with a call because I don't want control to return to that function. The function that is jumped to by the function a() should be of the same type so and parameter accessing/returning will (hopefully) be compatible. Quote:
08048468 <a>: 8048468: e9 1a 00 00 00 jmp 8048487 <b> 804846d: e9 15 00 00 00 jmp 8048487 <b> Evidently the address is relative so I must be using the wrong opcode. Is there a chart somewhere on available opcodes and their binary representation? Google turns up very little, and I got this code from a objdump disassembly :\ |
||
|
|
|
|
|
#8 | |
|
Programming Guru
![]() Join Date: Jun 2005
Location: elemental plane
Posts: 1,429
Rep Power: 5
![]() |
Quote:
__________________
"Employ your time in improving yourself by other men's writings, so that you shall gain easily what others have labored hard for." -- Socrates |
|
|
|
|
|
|
#9 |
|
Newbie
Join Date: Nov 2005
Posts: 4
Rep Power: 0
![]() |
> Is there a chart somewhere on available opcodes and their binary representation?
I sort of totally love OPCODES.HLP ![]() http://www.google.de/search?hl=de&q=opcodes.hlp&spell=1 I use winhelp in Wine on Linux to access this file. Had to get a friend to send me a dll and I think some other Windows file to make it work though NASM has a ton of good docs as well, including an x86 reference:http://nasm.sourceforge.net/doc/html/nasmdocb.html (BTW, this will be my last post in this forum, but you can PM me if you run into more problems regarding this interesting project.) |
|
|
|
|
|
#10 | |
|
Programmer
Join Date: Dec 2005
Posts: 65
Rep Power: 3
![]() |
Quote:
![]() As a follow up I was able to solve the issue with using a relative address like you said before. Copied the 4 byte offset to the target function which was calculated with (dest - (source + 5)). Invoking the source() function now "redirects" to the dest() function as desired. Thanks everyone for your help. |
|
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|