I’m not really getting how this code does what it does:
char shellcode[] = "\xbb\x00\x00\x00\x00"
"\xb8\x01\x00\x00\x00"
"\xcd\x80";
int main()
{
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
Okay, I know:
int *ret;
sets a pointer of int.
and:
ret = (int *)&ret + 2;
sets the address of ret and 2 bytes (I think.)
But I don’t get what this means:
(int *)&ret
I know what &ret means but not what (int *)&ret means.
Also, how does it execute the shellcode by assigning the value of shellcode to ret?
UPDATE:
What is the difference between:
(int *)&ret + 2
and:
&ret + 2
The ‘string’
shellcodecontains some machine code of some sort.The
int *ret;defines a variableretwhich is a pointer to anint.The assignment
ret = (int *)&ret + 2;makesretpoint to a location the size of twointfrom its own actual location (or address); this is an address in the stack, presumably where the return address of the function (main()) is stored on the stack.The assignment
*ret = (int)shellcode;assigns the address of the shell code to the return address. Therefore, when themain()function exits, the return address is the shell code, which does whatever it does instead of exiting the program normally.The casts cover up a multitude of sins. The code makes a large number of non-portable assumptions which are probably justified on the target environment but not necessarily anywhere else.
Type, mainly; this is one of the multitude of sins mentioned previously.
&rethas the typeint **(pointer to pointer toint) instead ofint *which is the type ofretitself. Sincesizeof(int *) == sizeof(int **)on all actual machines, the cast merely quells a complaint from the compiler (about assigning the wrong type of pointer toret) without changing the numerical result.