Why my shellcode does not work (in Linux)?
I wrote a small shellcode below:
#include <stdlib.h>
int main()
{
__asm__("jmp calloffsetn"
"poploffset: popl %%esin"
"movl $1,%%eaxn"
"movl $6,%%ebxn"
"int $0x80n"
"calloffset: call poploffsetn"
".string "/bin/bash"n":::"esi");
exit(1);
}
When the shellcode work, it will return 6. Actually, the code above works well, main function return 6 indeed.
And then I embed the code into a C program:
#include <stdlib.h>
#include <unistd.h>
char shellcode[]="xebx0dx5exb8x01x00x00x00xbbx06x00x00x00xcdx80xe8xeexffxffxff";
void func()
{
int * ret;
ret=(int *)&ret+0x08;
*ret=(int *)shellcode;
}
int main()
{
func();
exit(0);
}
Under normal circumstances, the code should return 6. But it return 0 all the time.
I don't think my code is wrong. I will show you that.
First, I get the address of val ret from gdb:
(gdb) print &ret
$1 = (int **) 0xbffff2f4
And I get the address of the next instruction of call in main:
(gdb) disass main
Dump of assembler code for function main:
0x08048ccb <+0>: push %ebp
0x08048ccc <+1>: mov %esp,%ebp
0x08048cce <+3>: and $0xfffffff0,%esp
0x08048cd1 <+6>: sub $0x10,%esp
0x08048cd4 <+9>: call 0x8048cb0 <func>
0x08048cd9 <+14>: movl $0x0,(%esp)
0x08048ce0 <+21>: call 0x80495c0 <exit>
End of assembler dump.
Obviously, it is 0x08048cd9.
And then, I get the address which store the address above in the stack:
(gdb) x/16xw $esp
0xbffff2e8: 0xbffff3bc 0x00000001 0x00000000 0x08049460
0xbffff2f8: 0xbffff318 0x08048cd9 0x0804972f 0x080d6044
0xbffff308: 0x08049797 0x00000000 0x08049460 0x080493c0
0xbffff318: 0x00000000 0x08048e91 0x00000001 0xbffff3b4
Obviously, the address is 0xbffff2f8+0x04=0xbffff2fc. And the address of val ret is 0xbffff2f4.
So, ret=(int *)&ret+0x08
should get the right address. And *ret=(int *)shellcode
should insert the address of the shellcode into the stack. And then the program runs into the shellcode, and finally I get 6 when the program return.
Am I wrong?
I seem to find the wrong place:
(gdb) disass func
Dump of assembler code for function func:
0x08048cb0 <+0>: push %ebp
0x08048cb1 <+1>: mov %esp,%ebp
0x08048cb3 <+3>: sub $0x28,%esp
0x08048cb6 <+6>: lea -0xc(%ebp),%eax
0x08048cb9 <+9>: add $0x20,%eax
0x08048cbc <+12>: mov %eax,-0xc(%ebp)
0x08048cbf <+15>: mov -0xc(%ebp),%eax
0x08048cc2 <+18>: mov $0x80d6028,%edx
0x08048cc7 <+23>: mov %edx,(%eax)
0x08048cc9 <+25>: movl $0x1,(%esp)
0x08048cd0 <+32>: call 0x8053380 <sleep>
0x08048cd5 <+37>: leave
0x08048cd6 <+38>: ret
End of assembler dump.
The instruction add $0x20,%eax
is strange. How can this happen?
The instruction add $0x20,%eax
is strange. How can this happen?
int * ret;
ret=(int *)&ret+0x08;
That's how C pointer math works - this addition changes ret
by 0x08 * sizeof(int)
bytes. That's where 0x20
comes from. But Andy Ross's observation is correct, the compiler is free to arrange the stack frame how it wants, so any recompilation, especially with different compiler settings, can modify the frame layout.
The compiler is free to put the "ret" variable anywhere in the stack frame of func() that it wants. Presumably (I'm too lazy to work out the math from the disassembly) your offset of 8 is simply wrong. Note that there is a 40 byte frame being set up.
链接地址: http://www.djcxy.com/p/87126.html上一篇: smulwb汇编指令