0

I have an exe file and I want to have its hex bytes to load it in the memory of another process and then execute it (something like process injection). What I want is almost what this post implements. The payload in this post in calculator software and it works well, but I want to substitute it with each exe file that I want. In short, how can I do this exe to hex conversion in such a way that it can be executed in another process context?

Methods like copying hex of exe from hex editors and debugger, online exe to hex converters and also using c++ instructions to do this conversion was not successful for me. This is the code I wrote in Go language:

file, err := ioutil.ReadFile("...\\helper.exe")
if err != nil {
}
//fmt.Print(file)
f, err := os.Create("...\\fileInByte.txt")
if err != nil {
}
defer f.Close()
_, err = f.Write([]byte(file))
file2, err2 := ioutil.ReadFile("...\\fileInByte.txt")
if err2 != nil {
}
fmt.Print(file2)

And this is c++ code first instructions to load fileInByte.txt hex bytes for process injectio:

std::ifstream input("...\\fileInByte.txt", std::ios::binary);
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
unsigned char* my_payload;
my_payload = &buffer[0];
unsigned int my_payload_len = sizeof(my_payload);
...
...
...


// allocate memory buffer for remote process
rb = VirtualAllocEx(ph, NULL, my_payload_len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// write payload to memory buffer
if(!WriteProcessMemory(ph, rb, my_payload, my_payload_len, NULL))
tadman
  • 208,517
  • 23
  • 234
  • 262
  • 1
    Hex bytes load it what? Normally you just run code as regular bytes. Hex is just for humans. – tadman Nov 06 '22 at 05:15
  • @tadman There is no difference!! I mean loading and executing the bytes (I don't think the type of display of the bytes is important) – user16385455 Nov 06 '22 at 05:17
  • 1
    Just talk about "raw bytes" in that case then. "Hex bytes" means something specific, like hex-encoded dumps. – tadman Nov 06 '22 at 05:18
  • @tadman The problem now is not the type of display of bytes, you consider them as raw bytes! The main question is important – user16385455 Nov 06 '22 at 05:21
  • 2
    The question says "hex" so many times I'm not even going to bother removing them, but you should. I've tried to clarify in the title. You should also better explain where your code has problems. – tadman Nov 06 '22 at 05:22

2 Answers2

1

So, you need to print an executable as a C-style hex array because you need to replace the payload in the C++ program, right?

Then you don't need go or c++ for that. The utility xxd -i does the trick: xxd -i super_duper_kill_em_all_malware.exe prints the hex array of super_duper_kill_em_all_malware.exe

But if it is too complicated for you, here is a simple Go program that does almost the same:

package main

import (
    "fmt"
    "io"
    "os"
    "path"
)

func main() {
    if len(os.Args) == 1 {
        die("Missing file name")
    }
    fname := os.Args[1]
    file, err := os.Open(fname)
    if err != nil {
        die_f("Failed to open %s: %s", fname, err.Error())
    }
    defer file.Close()

    // Print 16 bytes in a row
    buf := make([]byte, 16)
    first := true
    for {
        n, err := io.ReadFull(file, buf)
        if err != nil {
            if err == io.EOF {
                break
            }
            if err != io.ErrUnexpectedEOF {
                file.Close()
                die_f("Error reading %s: %s", fname, err.Error())
            }
        }
        // finish the previous line
        if !first {
            fmt.Println(",")
        }
        // Print the first column
        fmt.Printf("0x%02x", buf[0])
        // Print other columns
        for i := 1; i < n; i++ {
            fmt.Printf(", 0x%02x", buf[i])
        }
        first = false
    }
    fmt.Println()
}

func usage() {
    progname := path.Base(os.Args[0])
    fmt.Fprintf(os.Stderr, "%s FILE\n\n", progname)
    fmt.Fprintf(os.Stderr, "Prints the file as C-style hex array\n")
}

func die(msg string) {
    fmt.Fprintln(os.Stderr, msg)
    fmt.Fprintln(os.Stderr)
    usage()
    os.Exit(1)
}

func die_f(format string, vals ...any) {
    fmt.Fprintf(os.Stderr, format, vals...)
    fmt.Fprintln(os.Stderr)
    fmt.Fprintln(os.Stderr)
    usage()
    os.Exit(1)
}

Example: C-style hex array of go.mod

$ go run . go.mod
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f,
0x72, 0x67, 0x0a, 0x0a, 0x67, 0x6f, 0x20, 0x31, 0x2e, 0x31, 0x39, 0x0a

(here is what's inside go.mod:

module example.org

go 1.19

)

Pak Uula
  • 2,750
  • 1
  • 8
  • 13
  • Thanks. I used xxd as you said. my exe file that I need its C-style hex array is a c++ program output (.exe) that perform an operation like showing a message box or creating a file or ... . I have generated its C-style hex array in the way you said and I put it in the c++ program in my_payload array in: https://cocomelonc.github.io/tutorial/2021/11/23/malware-injection-6.html. But still the program I want was not executed (showing message box or creating a file or ...). – user16385455 Nov 06 '22 at 07:26
  • Did you compile it as the post author did? In mingw, static, with all the flags? – Pak Uula Nov 06 '22 at 08:16
  • No, but by my compiling settings, the author code (for calculator program) run successfully, but not my program. – user16385455 Nov 06 '22 at 10:12
  • @user16385455 You need exactly the same compiler flags. Typical binary can't be injected, it requires dynamic linking beforehand. Build exactly as the post author. – Pak Uula Nov 06 '22 at 11:05
  • Thank you very much for your detailed explanation. Is it possible to explain a little about how to compile? In "x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive >/dev/null 2>&1" we have two paths: "/usr/share/mingw-w64/include/" and "/dev/null 2>&1". I have no idea about the second path. How and where should it be referenced in Windows? (because apparently the author used Kali Linux for routing) – user16385455 Nov 06 '22 at 12:03
  • Unfortunately, despite using the flags suggested by the author of the post, such a code was not able to execute any other file – user16385455 Nov 13 '22 at 10:20
1

So you want to do DLL Injection, but with EXE, right?

LoadLibrary approach

When injecting a DLL, what you would normally do is create a remote thread in the target process that calls LoadLibrary to load your DLL, interestingly, LoadLibrary can load EXEs.

The main difference between DLLs and EXEs is that DLLs have the flag IMAGE_FILE_DLL set in its PE characteristics, so when LoadLibrary is called, it will try to map the DLL into memory, fix its IAT table and call its entry point.

When using LoadLibrary on an EXE, it doesn't have the flag IMAGE_FILE_DLL so it only gets mapped into memory, the IAT is left untouched and its entry point is never called.

You could manually set the IMAGE_FILE_DLL in an EXE characteristics and load it, but it would fail to call the entry point because of the differences between DLLs and EXEs. A workaround is to remove the entry point in the PE header entirely and manually call it.

Manual mapping approach

The idea of Manual mapping is to get rid of LoadLibrary, and try to manually map our DLL into the memory space, fix its IAT, and call its entry point - basically recreating the LoadLibrary function. Of course, by manual mapping, we could avoid patching the PE header as described above.

There are plenty of codes and libraries found on the internet, both external and internal.

Related links

  1. MemoryModule library: For manual mapping internally, supports EXEs, I used this to solve this exact problem.
  2. Load EXE as DLL: Mission Possible
thedemons
  • 1,139
  • 2
  • 9
  • 25