写在前面:
公众号偶尔会发广告的时,想必老粉丝已经习惯了,一些新朋友可能有一些对广告有一些误解,广告标题、内容皆为投放商所定,如果觉得广告浪费时间大家可以不点进来,如果想赞助一下,可以点进来看一看,但请不要因为一个广告就在后台留言狂怼,所有的热爱都是在生活的前提上的,感谢理解。
该系列文章将简单的介绍Csharp在渗透测试中的使用方法,主要为win32的使用以及一些库的调用。本文为第一篇文章,将以一个dump lsass进程的程序为例,介绍Csharp的简单使用,文章不会介绍Csharp基础性的东西,对此有兴趣的可以移步微软官方文档,或各类Csharp基础教学书籍、视频进行学习。
win32的调用
在整个Csharp的使用过程中,最重要的就是win32的调用,由于Csharp不向C/C 可以直接调用win32api进行使用,所以我们一般使用一种叫做P/Invoke的方法在DLL中使用win32api。具体可参考官方文档:https://docs.microsoft.com/en-us/archive/msdn-magazine/2003/july/net-column-calling-win32-dlls-in-csharp-with-p-invoke
其基本调用形式可以参考下面的使用:
代码语言:javascript复制[DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType);
其数据类型的转换如下表:
windows数据类型的转换如下:
其他类表
那么如果一个一个的来进行修改无非是费时费力的,这里我们一般使用一个叫做http://www.pinvoke.net/的网站来帮我们实现api的调用过程,当然其也支持vs插件。比如我们需要一个messagebox的api,就可以直接在该网站上搜索该api
其给出了C#以及VB的调用方法,C#的调用方法如下:
代码语言:javascript复制[DllImport("user32.dll", SetLastError = true, CharSet= CharSet.Auto)]
public static extern int MessageBox(int hWnd, String text, String caption, uint type);
下面我们新建一个Csharp程序,然后来使用这个API。记得加入using System.Runtime.InteropServices;因为DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数的必要调用信息。
然后放入我们的代码并调用它:
代码语言:javascript复制using System;
using System.Timers;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
namespace Basic3
{
class Program
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int MessageBox(int hWnd, String text, String caption, uint type);
static void Main(string[] args) {
MessageBox(0, "Hello World!", "Hello Dialog", 0);
}
}
}
执行,成功弹框。
SharpDump
知道了如何调用win32,下面我们来编写一个dumplsass进程的小程序。dumplsass进程网上有很多的demo,其实更多的还是在使用MiniDumpWriteDump来进行内存dump,其原型如下:
代码语言:javascript复制BOOL MiniDumpWriteDump(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
那么这时候我们便可以用之前说的方法来调用这个api来进行使用了。之前的调用方法我们一般称为托管 调用 非托管,关于一些名词的解释请自行百度,这里不再过多解释。除了之前的方法还有一种就是调用UnmanagedFunctionPointer以获得自定义调用约定。一般用以回调函数。
代码语言:javascript复制[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public static delegate {callback};
那我们就可以这样来写
代码语言:javascript复制[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeHandle hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
一般的此类函数的调用方法如下:
代码语言:javascript复制var MyFunctionPointer = (DMyUserCallFunction)Marshal.GetDelegateForFunctionPointer(AddressOfFunction, typeof(DMyUserCallFunction));
那我们这里便是:
代码语言:javascript复制IntPtr createPtr = GetProcAddress(LoadLibrary("Dbghelp.dll"), "MiniDumpWriteDump");
MiniDumpWriteDump miniDumpWriteDump = (MiniDumpWriteDump)Marshal.GetDelegateForFunctionPointer(createPtr, typeof(MiniDumpWriteDump));
GetProcAddress、LoadLibrary可以这样导入:
代码语言:javascript复制//import Win32API
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string dll);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string name);
下面就是查找进程的问题了,Csharp提供了Process类,可以直接使用进程名称或者进程ID来进行查找:
代码语言:javascript复制Process.GetProcessById
最后就是MINIDUMP_TYPE的问题了,这个关系到dump时如何dump的问题,其原型如下:
代码语言:javascript复制typedef enum _MINIDUMP_TYPE {
MiniDumpNormal,
MiniDumpWithDataSegs,
MiniDumpWithFullMemory,
MiniDumpWithHandleData,
MiniDumpFilterMemory,
MiniDumpScanMemory,
MiniDumpWithUnloadedModules,
MiniDumpWithIndirectlyReferencedMemory,
MiniDumpFilterModulePaths,
MiniDumpWithProcessThreadData,
MiniDumpWithPrivateReadWriteMemory,
MiniDumpWithoutOptionalData,
MiniDumpWithFullMemoryInfo,
MiniDumpWithThreadInfo,
MiniDumpWithCodeSegs,
MiniDumpWithoutAuxiliaryState,
MiniDumpWithFullAuxiliaryState,
MiniDumpWithPrivateWriteCopyMemory,
MiniDumpIgnoreInaccessibleMemory,
MiniDumpWithTokenInformation,
MiniDumpWithModuleHeaders,
MiniDumpFilterTriage,
MiniDumpWithAvxXStateContext,
MiniDumpWithIptTrace,
MiniDumpScanInaccessiblePartialPages,
MiniDumpValidTypeFlags
} MINIDUMP_TYPE;
这里我们如果定义成MINIDUMP_TYPE类型,那么我们将需要把这些内容全部自己定义出来,而我们刚才把其定义成立Int,此时则只需要给其传递一个2进去即可,即表示完整dump。
最后效果如下:
当然这个程序还是又很多其他的问题的,比如还可以加入自动提权等等。最后的代码可以在这里找到:https://github.com/lengjibo/OffenSiveCSharp
下一篇文章中,将会介绍如何将UUID免杀法转换成Csharp程序,并引出Csharp的公开调用Api的库。