Skip to content

Commit

Permalink
[FEATURE] Allow to unload converted DLL
Browse files Browse the repository at this point in the history
  • Loading branch information
hasherezade committed Nov 21, 2022
1 parent 9f987b5 commit d7a7565
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 27 deletions.
70 changes: 53 additions & 17 deletions loader_v2/peloader.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <Windows.h>
#include "peb_lookup.h"
#include "peloader.h"

#define RELOC_32BIT_FIELD 3
#define RELOC_64BIT_FIELD 0xA
Expand Down Expand Up @@ -146,31 +147,66 @@ int __stdcall main(void *module_base)
if (pe->Signature != IMAGE_NT_SIGNATURE) {
return (-2);
}
IMAGE_DATA_DIRECTORY &relocDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
if (!relocDir.VirtualAddress) {
return (-3);
}
const ULONG_PTR oldBase = pe->OptionalHeader.ImageBase;
if (!relocate(relocDir, (BYTE*)module_base, oldBase)) {
return (-4);

min_hdr_t* my_hdr = (min_hdr_t*)module_base;
if (my_hdr->load_status == LDS_RUN) {
// do not allow to run again:
return ERROR_ALREADY_INITIALIZED;
}
IMAGE_DATA_DIRECTORY& importDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (importDir.VirtualAddress) {
if (!load_imports(iat, importDir, (BYTE*)module_base)) {
return (-5);
if (my_hdr->load_status == LDS_ATTACHED) {
if ((pe->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
// not a DLL, this should not happed:
return ERROR_ALREADY_INITIALIZED;
}
DWORD ep_rva = pe->OptionalHeader.AddressOfEntryPoint;
ULONG_PTR ep_va = (ULONG_PTR)module_base + ep_rva;
BOOL(WINAPI * my_DllMain)(HINSTANCE, DWORD, LPVOID)
= (BOOL(WINAPI*)(HINSTANCE, DWORD, LPVOID)) ep_va;
BOOL is_ok = my_DllMain((HINSTANCE)module_base, DLL_PROCESS_DETACH, 0);
if (is_ok) {
// no longer attached:
my_hdr->load_status = LDS_RUN;
}
return is_ok;
}
IMAGE_DATA_DIRECTORY& tlsDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
if (tlsDir.VirtualAddress) {
run_tls_callbacks(tlsDir, (BYTE*)module_base);
if (my_hdr->load_status == LDS_CLEAN) {
IMAGE_DATA_DIRECTORY& relocDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
if (!relocDir.VirtualAddress) {
return (-3);
}
const ULONG_PTR oldBase = pe->OptionalHeader.ImageBase;
if (!relocate(relocDir, (BYTE*)module_base, oldBase)) {
return (-4);
}
IMAGE_DATA_DIRECTORY& importDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (importDir.VirtualAddress) {
if (!load_imports(iat, importDir, (BYTE*)module_base)) {
return (-5);
}
}
IMAGE_DATA_DIRECTORY& tlsDir = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
if (tlsDir.VirtualAddress) {
run_tls_callbacks(tlsDir, (BYTE*)module_base);
}
}
my_hdr->load_status = LDS_LOADED;

DWORD ep_rva = pe->OptionalHeader.AddressOfEntryPoint;
ULONG_PTR ep_va = (ULONG_PTR)module_base + ep_rva;
BOOL is_ok = FALSE;

my_hdr->load_status = LDS_RUN;
if (pe->FileHeader.Characteristics & IMAGE_FILE_DLL) {
BOOL(WINAPI * my_DllMain)(HINSTANCE, DWORD, LPVOID)
= (BOOL(WINAPI*)(HINSTANCE, DWORD, LPVOID)) ep_va;
return my_DllMain((HINSTANCE)module_base, DLL_PROCESS_ATTACH, 0);
is_ok = my_DllMain((HINSTANCE)module_base, DLL_PROCESS_ATTACH, 0);
if (is_ok) {
my_hdr->load_status = LDS_ATTACHED;
}
}
else {
int(*my_main)() = (int(*)()) (ep_va);
is_ok = my_main();
}
int(*my_main)() = (int(*)()) (ep_va);
return my_main();
return is_ok;
}
14 changes: 14 additions & 0 deletions loader_v2/peloader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once
#include <Windows.h>

#define MAX_REDIR_SIZE 32

#define LDS_CLEAN 0
#define LDS_LOADED 1
#define LDS_RUN 2
#define LDS_ATTACHED 3

typedef struct _min_hdr {
BYTE redir[MAX_REDIR_SIZE];
BYTE load_status;
} min_hdr_t;
11 changes: 9 additions & 2 deletions pe2shc/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "resource.h"

#define VERSION "1.1"
#include "..\loader_v2\peloader.h"

bool overwrite_hdr(BYTE *my_exe, size_t exe_size, DWORD raw, bool is64b)
{
Expand Down Expand Up @@ -62,10 +63,16 @@ bool overwrite_hdr(BYTE *my_exe, size_t exe_size, DWORD raw, bool is64b)
}
#endif
if (!redir_code) return false;

if (redir_size > MAX_REDIR_SIZE) {
std::cerr << "The selected redir stub exceed the maximal size: " << std::dec << MAX_REDIR_SIZE << "\n";
return false;
}
size_t offset = redir_size - value_pos;
memcpy(redir_code + offset, &raw, sizeof(DWORD));
memcpy(my_exe, redir_code, redir_size);

min_hdr_t* my_hdr = (min_hdr_t*)my_exe;
memcpy(my_hdr->redir, redir_code, redir_size);
my_hdr->load_status = LDS_CLEAN;
return true;
}

Expand Down
Binary file modified pe2shc/stub2/stub32.bin
Binary file not shown.
Binary file modified pe2shc/stub2/stub64.bin
Binary file not shown.
15 changes: 7 additions & 8 deletions runshc/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <iostream>

#include <peconv.h>
#include "..\loader_v2\peloader.h"

typedef struct {
BYTE* my_exe;
Expand Down Expand Up @@ -29,14 +30,12 @@ bool load_and_run(t_module_params& args)
int (*my_main)() = (int(*)()) ((ULONGLONG)test_buf);
int ret_val = my_main();
args.is_run = true;
if (peconv::is_module_dll(test_buf)) {
//unload DLL:
DWORD ep_rva = peconv::get_entry_point_rva(test_buf);
std::cout << "Unload DLL, RVA: " << ep_rva << "\n";
ULONG_PTR ep_va = (ULONG_PTR)test_buf + ep_rva;
BOOL(WINAPI * my_DllMain)(HINSTANCE, DWORD, LPVOID)
= (BOOL(WINAPI*)(HINSTANCE, DWORD, LPVOID)) ep_va;
my_DllMain((HINSTANCE)test_buf, DLL_PROCESS_DETACH, 0);
min_hdr_t *my_hdr = (min_hdr_t*)test_buf;
if (my_hdr->load_status == LDS_ATTACHED) {
//run again to unload DLL:
std::cout << "Running again to unload the DLL!\n";
my_main();
std::cout << "Load status: " << (int)my_hdr->load_status << "\n";
}
peconv::free_aligned(test_buf, args.exe_size);
std::cout << "[+] The shellcode finished with a return value: " << std::hex << ret_val << std::endl;
Expand Down

0 comments on commit d7a7565

Please sign in to comment.