0. API编程中的小技巧
0.1 获取错误信息
这一块主要是利用GetLastError这个API来获取,其操作非常简单,但是其默认返回的为DWORD类型,
DWORD GetLastError(void);
因此我们可以先转换为int类型,再根据int类型来查找其具体错误信息。
举个例子,我们使用DeleteFileA来删除一个文件,如果错误这里面输出报错代码。
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#pragma comment(lib,"netapi32")
int Usage(wchar_t*);
int wmain(int argc, wchar_t* argv[])
{
DeleteFileA("c:\\w.txt");
int x = GetLastError();
printf("%d\n", x);
}
运行以后我们看到其报错代码为2:
然后通过工具-错误查找,输入错误的值2,可以看到其提示“系统找不到指定的文件”
这主要是其目录下不存在这个文件
1. API概述
1.1 数据类型
Windows API 函数的参数、返回值或一些重要的常量使用的数据类型都是 Windows 数据类型。
1.2 Windows API功能分类
Windows API 所能实现的功能包括很多方面,在进行应用程序的开发时,开发人员可能会使用到文件、进程、内存、权限、系统信息等系统的基本服务和系统管理类的 API,可能会用到图形用户界面、控件等函数和对象,可能需要在界面上绘制图像处理多媒体信息等,还包括进行网络通信开发等。
文件
进程
内存
权限
网络
通信
图形用户界面
控件等函数和对象
系统信息等系统的基本服务
系统管理类的API
......
1.3 Windows API核心DLL
1.3.1 Kernel32.dll
1.3.2 User32.dll
1.3.3 Gdi32.dll
2. 文件操作
2.1 文件操作API
3. 进程
每个进行都有PID和句柄,系统和其他进程可以通过PID或句柄对该进行进行调用与操作。
在创建进程时,系统将应用程序的可执行文件加载到内存中,设置相关环境后,开始启动执行。要运行一个程序(exe 文件),系统会创建进程。
系统先在自己的内存管理单元中构造出一个虚拟地址空间,供进程使用,然后将 exe 文件加载到进程的虚拟地址空间内存中指定的位置,配置程序数据和调用接口等,然后再创建主线程。进程是正在运行的程序,即程序的运行实例。
3.1 CreateRemoteThread API基础
关于这个API相关链接为:
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread
其数据结构为:
HANDLE CreateRemoteThread(
[in] HANDLE hProcess,
[in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize,
[in] LPTHREAD_START_ROUTINE lpStartAddress,
[in] LPVOID lpParameter,
[in] DWORD dwCreationFlags,
[out] LPDWORD lpThreadId
);
3.2 创建远程线程实践
相关的代码实现如下所示:
#include <stdio.h>
#include <Windows.h>
#define errorprint(name){printf("%s Error Code:%d\n",name,GetLastError());return 1;}
bool EnbalePrivileges() {
HANDLE hToken = NULL;
LUID luidValue = { 0 };
TOKEN_PRIVILEGES tp = { 0 };
DWORD wdret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
if (wdret == NULL) {
errorprint("OpenProcessToken");
}
BOOL privilege = LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &luidValue);
if (privilege == false) {
errorprint("LookupPrivilegeValueA Privilege:SeDebugPrivilege");
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luidValue;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bool bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
if (bRet == false) {
errorprint("Enable Privilege Failure\n");
}
if (GetLastError() == ERROR_SUCCESS) {
printf("Enable Privilege:SeDebugPrivilege Sucess\n");
}
}
int main()
{
int pid = 5708;
EnbalePrivileges();
char* dllname = "C:\\Users\\Administrator\\Desktop\\test.dll";
int dllnamesize = strlen(dllname) * 2;
HANDLE pidmodule = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (pidmodule == NULL) {
printf("OpenProcess Error Code:%d\n", GetLastError());
return 1;
}
printf("OpenProcess HANDLE 0x%x\n", pidmodule);
LPVOID vaeAddr = VirtualAllocEx(pidmodule, NULL, dllnamesize, MEM_COMMIT, PAGE_READWRITE);
if (vaeAddr == NULL) {
printf("VirtualAllocEx Error Code:%d\n", GetLastError());
return 1;
}
printf("VirtualAllocEx Sucess 0x%x\n", vaeAddr);
if (false == WriteProcessMemory(pidmodule, vaeAddr, dllname, dllnamesize, NULL)) {
printf("WriteProcessMemory Error Code:%d\n", GetLastError());
return 1;
}
printf("WriteProcessMemory Sucess\n");
FARPROC loadaddress = GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryA");
if (loadaddress == NULL) {
printf("Get Kernel32 Address Error Code:%d\n", GetLastError());
return 1;
}
printf("Get Function LoadlibraryA Function Address:0x%x\n", loadaddress);
HANDLE runthread = CreateRemoteThread(pidmodule, NULL, 0, (LPTHREAD_START_ROUTINE)loadaddress, vaeAddr, 0, NULL);
if (runthread == NULL) {
printf("CreateRemoteThread Error Code:%d\n", GetLastError());
}
printf("CreateRemoteThread Sucess\n");
system("pause");
return 0;
}
在64位下编译:![](https://cdn.nlark.com/yuque/0/2021/png/12498619/1631329990222-3bc996ba-9f8f-4cd4-8c1e-f03eacb5ae63.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_6aOe6bif%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#from=url&id=y5LQs&margin=%5Bobject%20Object%5D&originHeight=571&originWidth=1004&originalType=binary&ratio=1&status=done&style=none)<br />可以看到,运行成功。<br />![](https://cdn.nlark.com/yuque/0/2021/png/12498619/1631330013073-9c9053c0-d2ac-4082-a116-0a171cf9d9df.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6aOe6bif%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#from=url&id=yWxgn&margin=%5Bobject%20Object%5D&originHeight=242&originWidth=726&originalType=binary&ratio=1&status=done&style=none)