Skip to content

Commit

Permalink
Merge pull request #1 from jstrosch/produce_pe
Browse files Browse the repository at this point in the history
Adds ability to produce 32/64-bit PE files from shellcode
  • Loading branch information
jstrosch authored Jan 26, 2024
2 parents 2546ee3 + 855cfcb commit ffe565d
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 62 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# SCLauncher - Basic Shellcode Tester and Debugger
# SCLauncher - Basic Shellcode Tester, Debugger and PE-File Wrapper

This program is designed to load 32-bit shellcode and allow for execution or debugging. The provided binary can be found in the `binaries` folder with a SHA 256 of `8fe5bd48daa90fe4be9321244912d23e0ede5010d4ea72a66c66fabe66c03d2e`.
This program is designed to load 32-bit or 64-bit shellcode and allow for execution or debugging. In addition, it can produce executable PE files based on the desired shellcode. This can ease testing as the output binary can be used by standard reverse engineering tools (i.e. IDA Pro (even free) and debuggers).

<img src="images/help.png">

You can view a demo of this tool on [YouTube](https://youtu.be/U8SkM99TB2g)
Release binaries are available. You can view a demo of this tool on [YouTube](https://youtu.be/U8SkM99TB2g)

## Compiling From Source

Expand All @@ -24,4 +24,10 @@ You can use the ```-f``` argument to define a path to a file that contains shell

The source code also allows for the inclusion of shellcode through an internal array, named ```shellcode```. The bytes of shellcode must be copied into the array value and the size of the array adjusted. The program can then be compiled and executed - this mode does not support the ```-f``` argument.

<img src="images/internal.png">
<img src="images/internal.png">

## Producing a PE file

You can use the ```-pe``` argument to produce a PE file that essentially wraps the shellcode. The shellcode is placed in the ```.text``` section. The entry point is defined as the beginning of the section, unless the ```-ep``` argument is used. This argument will define an offset from the beginning of the section and be used to update the PE files entry point (i.e. AddressOfEntry field). Additionally, the ```-64``` argument can be used to generate a 64-bit PE file, likely for 64-bit shellcode. The resulting PE file can be analyzed via common reverse engineering tools such as IDA Pro, Ghidra or a debugger such as x32dbg/WinDbg/etc.

<img src="images/produce_pe.png">
Binary file removed binaries/sclauncher.exe
Binary file not shown.
Binary file modified images/help.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/produce_pe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
226 changes: 226 additions & 0 deletions pe_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
#include <malloc.h>

struct _IMAGE_DOS_STUB
{
char data[64];
//char rich_header[104];
};

int round_up(int val) {
val = val / 1000;
if ((int)val % 1000 > 0){
val++;
}
val *= 1000;
return val;
}

void create_pe(char * sc_inject, int shellcode_size, int entry_point, int is_64) {
unsigned int tmp_offset = 0, section_padding = 0;
char* padding_buffer = NULL;
FILE*fp = NULL, *pe = NULL;

struct _IMAGE_DOS_HEADER idh = {
0x5A4D,
0x0090,
0x0003,
0x0000,
0x0004,
0x0000,
0xFFFF,
0x0000,
0x00B8,
0x0000,
0x0000,
0x0000,
0x0040,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x00000080,
};

struct _IMAGE_DOS_STUB ids = {0};
memmove(&ids.data, "Brought to you by sclauncher.exe",33);

struct _IMAGE_FILE_HEADER ifh = {
0x14C,
0x0001,
0,
0,
0,
224,
0x0102
};

struct _IMAGE_OPTIONAL_HEADER ioh = {
0x10B,
14,
16,
0,
0,
0,
0x1000,
0x1000,
0,
0x400000,
0x1000,
0x200,
6,
0,
0,
0,
6,
0,
0,
0,
0x400,
0,
3,
0x8140,
0x100000,
0x1000,
0x100000,
0x1000,
0,
0,
0
};

struct _IMAGE_OPTIONAL_HEADER64 ioh64 = {
0x20B,//PE32+
14,
16,
0,
0,
0,
0x1000,
0x1000,
0x400000,
0x1000,
0x200,
6,
0,
0,
0,
6,
0,
0,
0,
0x400,
0,
3,
0x8140,
0x100000,
0x1000,
0x100000,
0x1000,
0,
0,
0
};

struct _IMAGE_NT_HEADERS inh = {
0x00004550,
ifh,
ioh
};

struct _IMAGE_NT_HEADERS64 inh64 = {
0x00004550,
ifh,
ioh64
};

struct _IMAGE_SECTION_HEADER ish = {
".josh",
0,
0x1000,
0,
0x400,
0,
0,
0,
0,
0xE0000020
};

puts("[PE] Adding shellcode...");

//update lfanew based on size of image_dos_header and image_dos_stub
idh.e_lfanew = (sizeof(idh) + sizeof(ids));

//calculate difference between headers and first section
if (is_64) {
section_padding = 0x400 - (sizeof(idh) + sizeof(ids) + sizeof(inh64) + sizeof(ish));
} else {
section_padding = 0x400 - (sizeof(idh) + sizeof(ids) + sizeof(inh) + sizeof(ish));
}

//update entry point
if( entry_point ) {
if(is_64) {
inh64.OptionalHeader.AddressOfEntryPoint = entry_point + 0x1000;
} else {
inh.OptionalHeader.AddressOfEntryPoint = entry_point + 0x1000;
}
}

//update the raw and virtual size of the section
ish.SizeOfRawData = shellcode_size;
ish.Misc.VirtualSize = shellcode_size;

if (is_64) {
inh64.FileHeader.Machine = 0x8664;
inh64.OptionalHeader.SizeOfCode = shellcode_size;
inh64.OptionalHeader.SizeOfImage = round_up(shellcode_size + 0x1000);
inh64.FileHeader.SizeOfOptionalHeader = sizeof(inh64.OptionalHeader);

inh64.FileHeader.TimeDateStamp = time(NULL);
} else {
inh.OptionalHeader.SizeOfCode = shellcode_size;
//virtual address + section size rounded up. shellcode size will equal section size
inh.OptionalHeader.SizeOfImage = round_up(shellcode_size + 0x1000);
inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader);

inh.FileHeader.TimeDateStamp = time(NULL);
}

//create array for padding bytes
padding_buffer = (char*)calloc(section_padding,1);

if (is_64) {
pe = fopen("sc_output_x64.exe", "wb");
printf("[PE] Done building PE file...created file sc_output_x64.exe\n");
} else {
pe = fopen("sc_output.exe", "wb");
printf("[PE] Done building PE file...created file sc_output.exe\n");
}
fwrite(&idh,sizeof(idh),1,pe);
fwrite(&ids,sizeof(ids),1,pe);
if(is_64) {
fwrite(&inh64,sizeof(inh64),1,pe);
} else {
fwrite(&inh,sizeof(inh),1,pe);
}
fwrite(&ish,sizeof(ish),1,pe);
fwrite(padding_buffer, _msize(padding_buffer),1,pe);
fwrite(sc_inject,shellcode_size, 1, pe);

fclose(pe);
free(padding_buffer);
}
Loading

0 comments on commit ffe565d

Please sign in to comment.