Skip to content

Commit

Permalink
v2.1.0, support gui on Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
xicilion committed Oct 20, 2024
1 parent 5ddc1c6 commit 79b876a
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 68 deletions.
37 changes: 9 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ const path = require('path');
module.exports = inject = require(`./addon/${path.basename(__dirname)}.node`);
module.exports.inject = function (filename, resourceName, resourceData, options) {
const machoSegmentName = options?.machoSegmentName || "__FIBINJECT";
const overwrite = options?.overwrite || false;
let sentinelFuse = options?.sentinelFuse || "FIBINJECT_SENTINEL_d0695dd05effa072dcb0b1f8f807ac40";
const sentinelFuse = options?.sentinelFuse || "FIBINJECT_SENTINEL_d0695dd05effa072dcb0b1f8f807ac40";
const subsystem = options?.subsystem || "cui";

if (subsystem !== "cui" && subsystem !== "gui") {
throw new Error("Subsystem must be either 'cui' or 'gui'");
}

if (!Buffer.isBuffer(resourceData)) {
throw new TypeError("resourceData must be a buffer");
Expand Down Expand Up @@ -49,16 +53,8 @@ module.exports.inject = function (filename, resourceName, resourceData, options)
executable,
machoSegmentName,
sectionName,
resourceData,
overwrite
resourceData
));

if (result === inject.InjectResult.kAlreadyExists) {
throw new Error(
`Segment and section with that name already exists: ${machoSegmentName}/${sectionName}\n` +
"Use --overwrite to overwrite the existing content"
);
}
}
break;

Expand All @@ -71,16 +67,8 @@ module.exports.inject = function (filename, resourceName, resourceData, options)
({ result, data } = inject.inject_into_elf(
executable,
sectionName,
resourceData,
overwrite
resourceData
));

if (result === inject.InjectResult.kAlreadyExists) {
throw new Error(
`Section with that name already exists: ${sectionName}` +
"Use --overwrite to overwrite the existing content"
);
}
}
break;

Expand All @@ -93,15 +81,8 @@ module.exports.inject = function (filename, resourceName, resourceData, options)
executable,
resourceName,
resourceData,
overwrite
subsystem === "gui"
));

if (result === inject.InjectResult.kAlreadyExists) {
throw new Error(
`Resource with that name already exists: ${resourceName}\n` +
"Use --overwrite to overwrite the existing content"
);
}
}
break;
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fib-inject",
"version": "2.0.1",
"version": "2.1.0",
"description": "fibjs binding for inject representation and classification.",
"main": "index.js",
"scripts": {
Expand Down
5 changes: 2 additions & 3 deletions src/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
Napi::Object Initialize(Napi::Env env, Napi::Object exports)
{
Napi::Object executableFormat = Napi::Object::New(env);
executableFormat.Set(Napi::String::New(env, "kUnknown"), Napi::Number::New(env, kUnknown));
executableFormat.Set(Napi::String::New(env, "kELF"), Napi::Number::New(env, kELF));
executableFormat.Set(Napi::String::New(env, "kMachO"), Napi::Number::New(env, kMachO));
executableFormat.Set(Napi::String::New(env, "kPE"), Napi::Number::New(env, kPE));
executableFormat.Set(Napi::String::New(env, "kUnknown"), Napi::Number::New(env, kUnknown));
exports.Set(Napi::String::New(env, "ExecutableFormat"), executableFormat);

Napi::Object injectResult = Napi::Object::New(env);
injectResult.Set(Napi::String::New(env, "kAlreadyExists"), Napi::Number::New(env, kAlreadyExists));
injectResult.Set(Napi::String::New(env, "kError"), Napi::Number::New(env, kError));
injectResult.Set(Napi::String::New(env, "kSuccess"), Napi::Number::New(env, kSuccess));
injectResult.Set(Napi::String::New(env, "kError"), Napi::Number::New(env, kError));
exports.Set(Napi::String::New(env, "InjectResult"), injectResult);

exports.Set(Napi::String::New(env, "get_executable_format"), Napi::Function::New(env, get_executable_format));
Expand Down
9 changes: 4 additions & 5 deletions src/inject.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#include <napi.h>

enum ExecutableFormat {
kUnknown,
kELF,
kMachO,
kPE,
kUnknown
kPE
};

enum InjectResult {
kAlreadyExists,
kError,
kSuccess
kSuccess,
kError
};

// format detection declarations
Expand Down
12 changes: 3 additions & 9 deletions src/inject_into_elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ Napi::Value inject_into_elf(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();

if (info.Length() < 4 || !info[0].IsBuffer() || !info[1].IsString() || !info[2].IsBuffer() || !info[3].IsBoolean()) {
Napi::TypeError::New(env, "Expected (Buffer, string, Buffer, boolean)").ThrowAsJavaScriptException();
if (info.Length() < 3 || !info[0].IsBuffer() || !info[1].IsString() || !info[2].IsBuffer()) {
Napi::TypeError::New(env, "Expected (Buffer, string, Buffer)").ThrowAsJavaScriptException();
return env.Null();
}

Napi::Buffer<uint8_t> executable = info[0].As<Napi::Buffer<uint8_t>>();
std::string note_name = info[1].As<Napi::String>();
Napi::Buffer<uint8_t> data = info[2].As<Napi::Buffer<uint8_t>>();
bool overwrite = info[3].As<Napi::Boolean>();

Napi::Object result = Napi::Object::New(env);
result.Set("data", env.Undefined());
Expand Down Expand Up @@ -46,12 +45,7 @@ Napi::Value inject_into_elf(const Napi::CallbackInfo& info)
}

if (existing_note) {
if (!overwrite) {
result.Set("result", Napi::Number::New(env, InjectResult::kAlreadyExists));
return result;
} else {
binary->remove(*existing_note);
}
binary->remove(*existing_note);
}

std::unique_ptr<LIEF::ELF::Note> note = LIEF::ELF::Note::create(note_name, LIEF::ELF::Note::TYPE::GNU_BUILD_ATTRIBUTE_OPEN,
Expand Down
8 changes: 1 addition & 7 deletions src/inject_into_macho.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ Napi::Value inject_into_macho(const Napi::CallbackInfo& info)
Napi::Env env = info.Env();

if (info.Length() < 4 || !info[0].IsBuffer() || !info[1].IsString() || !info[2].IsString() || !info[3].IsBuffer()) {
Napi::TypeError::New(env, "Expected (Buffer, string, string, Buffer, boolean)").ThrowAsJavaScriptException();
Napi::TypeError::New(env, "Expected (Buffer, string, string, Buffer)").ThrowAsJavaScriptException();
return env.Null();
}

Napi::Buffer<uint8_t> executable = info[0].As<Napi::Buffer<uint8_t>>();
std::string segment_name = info[1].As<Napi::String>();
std::string section_name = info[2].As<Napi::String>();
Napi::Buffer<uint8_t> data = info[3].As<Napi::Buffer<uint8_t>>();
bool overwrite = info.Length() > 4 ? info[4].As<Napi::Boolean>() : false;

Napi::Object result = Napi::Object::New(env);
result.Set("data", env.Undefined());
Expand All @@ -32,11 +31,6 @@ Napi::Value inject_into_macho(const Napi::CallbackInfo& info)
LIEF::MachO::Section* existing_section = binary.get_section(section_name);

if (existing_section) {
if (!overwrite) {
result.Set("result", Napi::Number::New(env, InjectResult::kAlreadyExists));
return result;
}

binary.remove_section(section_name, true);
}

Expand Down
22 changes: 15 additions & 7 deletions src/inject_into_pe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@ Napi::Value inject_into_pe(const Napi::CallbackInfo& info)
Napi::Env env = info.Env();

if (info.Length() < 3 || !info[0].IsBuffer() || !info[1].IsString() || !info[2].IsBuffer()) {
Napi::TypeError::New(env, "Expected (Buffer, string, Buffer, boolean)").ThrowAsJavaScriptException();
Napi::TypeError::New(env, "Expected (Buffer, string, Buffer)").ThrowAsJavaScriptException();
return env.Null();
}

Napi::Buffer<uint8_t> executable = info[0].As<Napi::Buffer<uint8_t>>();
std::string resource_name = info[1].As<Napi::String>();
Napi::Buffer<uint8_t> data = info[2].As<Napi::Buffer<uint8_t>>();
bool overwrite = info.Length() > 3 ? info[3].As<Napi::Boolean>() : false;
bool gui_subsystem = false;

if (info.Length() > 3) {
if (!info[3].IsBoolean()) {
Napi::TypeError::New(env, "Expected (Buffer, string, Buffer, boolean)").ThrowAsJavaScriptException();
return env.Null();
}

gui_subsystem = info[3].As<Napi::Boolean>();
}

Napi::Object result = Napi::Object::New(env);
result.Set("data", env.Undefined());
Expand Down Expand Up @@ -69,11 +78,6 @@ Napi::Value inject_into_pe(const Napi::CallbackInfo& info)
}

if (!id_node->childs().empty()) {
if (!overwrite) {
result.Set("result", Napi::Number::New(env, InjectResult::kAlreadyExists));
return result;
}

id_node->delete_child(*id_node->childs().begin());
}

Expand All @@ -94,6 +98,10 @@ Napi::Value inject_into_pe(const Napi::CallbackInfo& info)

binary = LIEF::PE::Parser::parse(builder.get_build());

if (gui_subsystem) {
binary->optional_header().subsystem(LIEF::PE::OptionalHeader::SUBSYSTEM::WINDOWS_GUI);
}

LIEF::PE::Section* section = binary->get_section(".l2");
section->name(".rsrc");

Expand Down
17 changes: 9 additions & 8 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,17 @@ const inject_file = path.join(__dirname, "inject.exe");
describe('fib-inject', () => {
it("ExecutableFormat", () => {
assert.deepEqual(inject.ExecutableFormat, {
"kELF": 0,
"kMachO": 1,
"kPE": 2,
"kUnknown": 3
"kUnknown": 0,
"kELF": 1,
"kMachO": 2,
"kPE": 3
});
});

it("InjectResult", () => {
assert.deepEqual(inject.InjectResult, {
"kAlreadyExists": 0,
"kError": 1,
"kSuccess": 2
"kSuccess": 0,
"kError": 1
});
});

Expand Down Expand Up @@ -56,7 +55,9 @@ describe('fib-inject', () => {
});

fs.copyFile(test_file, inject_file);
inject.inject(inject_file, 'foobar', Buffer.from("Hello, fib-inject!"));
inject.inject(inject_file, 'foobar', Buffer.from("Hello, fib-inject!"), {
subsystem: "gui"
});

if (process.platform === 'darwin')
child_process.execFile(`codesign`, ["-s", "-", inject_file]);
Expand Down

0 comments on commit 79b876a

Please sign in to comment.