I have two questions related to C programming and shellcoding (assembly) following below.
Question 1: Can anyone provide an answer on why putting two shellcodes in one program wouldn't work? I know it's related to the memory region but I need to know the exact reason. Program is compiled using gcc with the -zexecstack
and -fno-stack-protector
options.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
unsigned char shellcode[] = "\x01\x02<SHELLCODE>";
/* if the below line is uncommmented it will result in segault */
/* unsigned char shellcode_[] = "\x01\x02<SHELLCODE>"; */
int (*ret)() = (int(*)())shellcode;
return 0;
}
So how would it be possible to divide multiple shellcodes into different memory regions and call them without them interrupting the execution flow between each other, and decide which one to call? (I mean just STORE two shellcodes, not RUN them simultaneously, if that's possible at all).
Question 2: if the shellcode has to be passed as a parameter to a function, what would be the proper way to do it?
Pseudocode:
unsigned char shellcode[] = "\x01\x02...";
void call_shellcode(unsigned char shellcode[200]);
main()
{
call_shellcode(shellcode);
}
void call_shellcode(unsigned char shellcode[200])
{
... print/call shellcode
}
UPDATE: As there seems to be some misunderstanding to the question, this is not the ACTUAL shellcode. I do know what shellcode is and how it is generated, and how it works. I have not provided an actual shellcode within the C stub to leave it in a readable state. The value "\x01\x01" is a pseudo code to point to the idea of the question and NOT any actual contents.
CodePudding user response:
Your shellcode cannot possibly work for a very simple reason: it begins with \x01\x02
:
unsigned char shellcode[] = "\x01\x02<SHELLCODE>";
I'm not sure why your think your shellcode has to begin with those two bytes: it really doesn't!
Those two bytes decode to add DWORD PTR [rdx],eax
(or edx
if running in 32-bit mode). Since you do not have any control over the value of RDX/EDX at the time your shellcode is called, it will very likely immediately cause a segmentation fault because RDX/EDX does not contain a valid (and writable) memory address.
Changing literally anything around the shellcode, in the function or outside, could cause the compiler to choose a different register allocation that will result in RDX/EDX having a good value at runtime that doesn't result in a crash, but that'd just be a lucky coincidence. Writing and using shellcode like this is inherently undefined behavior, or at least implementation defined (fixed an operating system and compiler) so extra care must be taken.
So how would it be possible to divide multiple shellcodes into different memory regions and call them without them interrupting the execution flow between each other, and decide which one to call?
Well, you're not really dividing anything in "different memory regions"... whether you use one array or two or ten, they are all declared on the stack and they will be close together on the stack.
If you want to jump from one to the other, that's going to be a complex task, because in general you do not know the location of a variable on the stack beforehand, so you will have to do some math calculating your current location and then the offset from one shellcode chunk to the other, ultimately performing a relative call/jump.
If shellcode has to be passed as a parameter to a function what would be the proper way to do this?
The proper way is to mmap
a region of memory that is RWX, write the shellcode into it (memcpy, read from stdin, etc.) and then pass a pointer to that memory region to the function you want. You have no guarantee that a piece of global data will be put by the compiler in an executable memory region. In fact, no modern day compiler would do that, and furthermore, no modern day kernel would map such a region as executable even if the ELF is compiled with -z execstack
.
In recent kernels -z execstack
is only respected for the stack itself, so passing a shellcode as function argument through a variable will only work if the variable was defined on the stack.
CodePudding user response:
You can't have two variables with the same name in the same scope (this part has nothing to do with what the variables are or how they are used). Simply give the second shellcode a different name.
Note I am not going to comment at all on what you are trying to do, other than that I would not think of manually created machine code as "shell code" (which I would usually think of as code intended for a command shell like bash).