views:

706

answers:

6

As an assignment for a security class, I am trying to use __asm__("jmp 0xbffff994"); in my code, but when I disassemble things in gdb, the instruction is changed to jmp 0xc8047e2a. Any idea why and how can I jump to a particular address?

A: 

I think what you are trying to do is a security problem. Your compiler is using offsets to prevent your program from doing something harmful.

Daniel A. White
Yeah, I am doing an exploit for a security class :)
Martin
What? How can that protect the program?
Mark
It would protect your program from accessing outside of itself.
Daniel A. White
At best, it would turn a pointer that happened to be valid into an invalid pointer, but it could equally do the opposite. Relocation is not about security. Are you thinking of ASLR?
Mark
Sorry Daniel, not correct, the problem is that there is x86 instruction to jmp to a direct offset. the jmp instruction takes an *offset*, a register, or a memory expression. in this case, the assembler treated the constant as an offset. That means that it is relative to the address of the instruction.
Evan Teran
A: 

Daniel Explains why your jump is not the same you programmed. It has to do with object files and linking.

if you want to jump to a particular address, it's best to patch the jump using a Debugger or Disassembler.

toto
+6  A: 

Probably because it's a jumping to a relative address, and the linker or loader has moved your code. Try putting the address into a variable, and then do:

jmp dword [var]

or alternatively:

push 0xbffff994
ret
Mark
*that* is the correct answer, also note that: "mov eax, 0x11223344; jmp eax"; will also work and is likely the most straight forward.
Evan Teran
very true, but he might be using fastcall (I'm not sure of the significance of 0xbffff994).
Mark
The PUSH RET combination works! Thank you!
Martin
0xbffff994 likely = a location on the stack on a linux box :-P
Evan Teran
A: 

On my system (gcc version 4.2.4, Ubuntu) this looks fine on the disassmbley (insight):

int main()
{
asm("jmp 0xbffff994"); 
return 0;
};       

results of the disassmbley (insight):

        0x8048344       :                 lea    0x4(%esp),%ecx
-       0x8048348       :               and    $0xfffffff0,%esp
-       0x804834b       :               pushl  -0x4(%ecx)
-       0x804834e       :              push   %ebp
-       0x804834f       :              mov    %esp,%ebp
-       0x8048351       :              push   %ecx
-       0x8048352       :              jmp    0xbffff994
-       0x8048357       :              mov    $0x0,%eax
-       0x804835c       :              pop    %ecx
-       0x804835d       :              pop    %ebp
-       0x804835e       :              lea    -0x4(%ecx),%esp
-       0x8048361       :              ret
Liran Orevi
I would guess that that disassembler is showing the offset of the jmp and not its actual target. (the jmp instruction takes an offset relative to eip when you give it a 32-bit immediate operand).
Evan Teran
Why would you guess that? is there a way to test it? it is running as a graphical interface with GDB below.
Liran Orevi
Or it could be that there's no relocation. However, if you dump the opcodes with the assembly you'll be able to see the offset.
Mark
I see this 8048352: e9 3d 76 fb b7 jmp bffff994 <_end+0xb7fb6454>can't find the _end label, but it looks mighty close to the end of the program.
Liran Orevi
A: 

It is hard to determine the exact address upon compile time, have you tried using labels? It is much more common to use them with jmp.

example:

start:
 jmp exit

exit:
 ret
John T
A: 

I would recommend using a hex editor and simply changing the value if it's just a one time thing.

samoz