I am using the windows api SystemFunction033 from advapi32.dll to do RC4 decryption/encryption. My problem is, i want to port my working c++ code to golang, but the golang code does not work. I dont get the right result and i think, i maybe wrongly use the unsafe.Pointers.
On the c++ code it will succesfully decrypt the RC4 encrypted word “Hello”, but on golang not:
C++
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
// https://doxygen.reactos.org/df/d13/sysfunc_8c_source.html
// Function prototype for SystemFunction033
typedef NTSTATUS(WINAPI* _SystemFunction033)(
struct ustring* memoryRegion,
struct ustring* keyPointer);
struct ustring {
DWORD Length;
DWORD MaximumLength;
PVOID Buffer;
} _data, key;
void printResult(const unsigned char* input, size_t size) {
// Iterate over each byte in the input array
for (size_t i = 0; i < size; i++) {
// Print each byte in hexadecimal format
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input[i]) << std::endl;
}
}
int main() {
// Load the library
HMODULE hAdvapi32 = LoadLibraryA("advapi32.dll");
if (hAdvapi32 == NULL) {
std::cerr << "Failed to load advapi32.dll" << std::endl;
return 1;
}
// Get the address of the function
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(hAdvapi32, "SystemFunction033");
if (SystemFunction033 == NULL) {
std::cerr << "Failed to get the address of SystemFunction033" << std::endl;
FreeLibrary(hAdvapi32);
return 1;
}
// Print the address
std::cout << "Address of SystemFunction033: " << std::hex << (void*)SystemFunction033 << std::endl;
char _key[] = "supersecretkey";
// Hello
// unsigned char input[] = { 0x48,0x65,0x6c,0x6c,0x6f };
// Hello but already RC4 Encrypted with key "supersecretkey"
unsigned char input[] = { 0xc6,0x22,0xb5,0x00,0x3a };
unsigned int input_size = sizeof(input);
int sizer = sizeof(input) / sizeof(input[0]); // Calculate the size of the array
// Convert each byte to its ASCII character equivalent and concatenate them
std::string str;
for (int i = 0; i < sizer; i++) {
str += input[i];
}
std::cout << "Encrypted: " << str << std::endl;
//Setting key values
key.Buffer = (&_key);
key.Length = sizeof(_key);
//Setting input in the struct for Systemfunction033
_data.Buffer = input;
_data.Length = input_size;
//Calling Systemfunction033
SystemFunction033(&_data, &key);
// Print the result in the desired format
std::cout << "Result:" << std::endl;
printResult(reinterpret_cast<unsigned char*>(_data.Buffer), _data.Length);
unsigned char* ptr = reinterpret_cast<unsigned char*>(_data.Buffer);
int sizex = sizeof(input) / sizeof(input[0]); // Calculate the size of the array
// Convert each byte to its ASCII character equivalent and concatenate them
std::string strx;
for (int i = 0; i < sizex; i++) {
strx += ptr[i];
}
std::cout << "Decrypted: " << strx << std::endl;
}
Golang
package main
import (
"fmt"
"syscall"
"unsafe"
)
type ustring struct {
Length uint32
MaximumLength uint32
Buffer unsafe.Pointer
}
var (
_data ustring
key ustring
)
func printResult(input []byte) {
// Iterate over each byte in the input slice
for _, b := range input {
// Print each byte in hexadecimal format with '0x' prefix
fmt.Printf("0x%02xn", b)
}
}
func main() {
systemfunction033 := syscall.NewLazyDLL("advapi32.dll").NewProc("SystemFunction033")
fmt.Printf("Address of SystemFunction033: %xn", systemfunction033.Addr());
// Define the key
_key := []byte("supersecretkey")
// Hello
// input := []byte{0x48,0x65,0x6c,0x6c,0x6f}
// Hello but already RC4 Encrypted with key "supersecretkey"
input := []byte{0xc6,0x22,0xb5,0x00,0x3a}
input_size := len(input)
// Convert each byte to its ASCII character equivalent and concatenate them
var str string
for _, b := range input {
str += string(b)
}
fmt.Println("Encrypted:", str)
// Set key values
key.Buffer = unsafe.Pointer(&_key[0])
key.Length = uint32(len(_key))
// Set input values
_data.Buffer = unsafe.Pointer(&input[0])
_data.Length = uint32(input_size)
// Call the function
_, _, _ = systemfunction033.Call(
uintptr(unsafe.Pointer(&_data)),
uintptr(unsafe.Pointer(&key)),
)
// Print the results
// fmt.Printf("Call Result: %v, %v, %vn", r1, r2, err)
// unsafe.Pointer to []byte
dataBytes := unsafe.Slice((*byte)(_data.Buffer), input_size)
printResult(dataBytes)
// Convert each byte to its ASCII character equivalent and concatenate them
var strx string
for _, b := range dataBytes {
strx += string(b)
}
fmt.Println("Decrypted:", strx)
}