0. API编程中的小技巧

0.1 获取错误信息

这一块主要是利用GetLastError这个API来获取,其操作非常简单,但是其默认返回的为DWORD类型,

  1. DWORD GetLastError(void);

因此我们可以先转换为int类型,再根据int类型来查找其具体错误信息。
举个例子,我们使用DeleteFileA来删除一个文件,如果错误这里面输出报错代码。

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <lm.h>
  4. #pragma comment(lib,"netapi32")
  5. int Usage(wchar_t*);
  6. int wmain(int argc, wchar_t* argv[])
  7. {
  8. DeleteFileA("c:\\w.txt");
  9. int x = GetLastError();
  10. printf("%d\n", x);
  11. }

运行以后我们看到其报错代码为2:
image.png
然后通过工具-错误查找,输入错误的值2,可以看到其提示“系统找不到指定的文件”
image.pngimage.png
这主要是其目录下不存在这个文件
image.png

1. API概述

1.1 数据类型

image.png
image.png
Windows API 函数的参数、返回值或一些重要的常量使用的数据类型都是 Windows 数据类型。
image.png

1.2 Windows API功能分类

Windows API 所能实现的功能包括很多方面,在进行应用程序的开发时,开发人员可能会使用到文件、进程、内存、权限、系统信息等系统的基本服务和系统管理类的 API,可能会用到图形用户界面、控件等函数和对象,可能需要在界面上绘制图像处理多媒体信息等,还包括进行网络通信开发等。

  1. 文件
  2. 进程
  3. 内存
  4. 权限
  5. 网络
  6. 通信
  7. 图形用户界面
  8. 控件等函数和对象
  9. 系统信息等系统的基本服务
  10. 系统管理类的API
  11. ......

image.png

1.3 Windows API核心DLL

image.png

1.3.1 Kernel32.dll

image.png

1.3.2 User32.dll

image.png

1.3.3 Gdi32.dll

image.png

2. 文件操作

2.1 文件操作API

image.png
image.png

3. 进程

每个进行都有PID和句柄,系统和其他进程可以通过PID或句柄对该进行进行调用与操作。
在创建进程时,系统将应用程序的可执行文件加载到内存中,设置相关环境后,开始启动执行。要运行一个程序(exe 文件),系统会创建进程。
系统先在自己的内存管理单元中构造出一个虚拟地址空间,供进程使用,然后将 exe 文件加载到进程的虚拟地址空间内存中指定的位置,配置程序数据和调用接口等,然后再创建主线程。进程是正在运行的程序,即程序的运行实例。

3.1 CreateRemoteThread API基础

关于这个API相关链接为:

  1. https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread

其数据结构为:

  1. HANDLE CreateRemoteThread(
  2. [in] HANDLE hProcess,
  3. [in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
  4. [in] SIZE_T dwStackSize,
  5. [in] LPTHREAD_START_ROUTINE lpStartAddress,
  6. [in] LPVOID lpParameter,
  7. [in] DWORD dwCreationFlags,
  8. [out] LPDWORD lpThreadId
  9. );

3.2 创建远程线程实践

相关的代码实现如下所示:

  1. #include <stdio.h>
  2. #include <Windows.h>
  3. #define errorprint(name){printf("%s Error Code:%d\n",name,GetLastError());return 1;}
  4. bool EnbalePrivileges() {
  5. HANDLE hToken = NULL;
  6. LUID luidValue = { 0 };
  7. TOKEN_PRIVILEGES tp = { 0 };
  8. DWORD wdret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
  9. if (wdret == NULL) {
  10. errorprint("OpenProcessToken");
  11. }
  12. BOOL privilege = LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &luidValue);
  13. if (privilege == false) {
  14. errorprint("LookupPrivilegeValueA Privilege:SeDebugPrivilege");
  15. }
  16. tp.PrivilegeCount = 1;
  17. tp.Privileges[0].Luid = luidValue;
  18. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  19. bool bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
  20. if (bRet == false) {
  21. errorprint("Enable Privilege Failure\n");
  22. }
  23. if (GetLastError() == ERROR_SUCCESS) {
  24. printf("Enable Privilege:SeDebugPrivilege Sucess\n");
  25. }
  26. }
  27. int main()
  28. {
  29. int pid = 5708;
  30. EnbalePrivileges();
  31. char* dllname = "C:\\Users\\Administrator\\Desktop\\test.dll";
  32. int dllnamesize = strlen(dllname) * 2;
  33. HANDLE pidmodule = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
  34. if (pidmodule == NULL) {
  35. printf("OpenProcess Error Code:%d\n", GetLastError());
  36. return 1;
  37. }
  38. printf("OpenProcess HANDLE 0x%x\n", pidmodule);
  39. LPVOID vaeAddr = VirtualAllocEx(pidmodule, NULL, dllnamesize, MEM_COMMIT, PAGE_READWRITE);
  40. if (vaeAddr == NULL) {
  41. printf("VirtualAllocEx Error Code:%d\n", GetLastError());
  42. return 1;
  43. }
  44. printf("VirtualAllocEx Sucess 0x%x\n", vaeAddr);
  45. if (false == WriteProcessMemory(pidmodule, vaeAddr, dllname, dllnamesize, NULL)) {
  46. printf("WriteProcessMemory Error Code:%d\n", GetLastError());
  47. return 1;
  48. }
  49. printf("WriteProcessMemory Sucess\n");
  50. FARPROC loadaddress = GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryA");
  51. if (loadaddress == NULL) {
  52. printf("Get Kernel32 Address Error Code:%d\n", GetLastError());
  53. return 1;
  54. }
  55. printf("Get Function LoadlibraryA Function Address:0x%x\n", loadaddress);
  56. HANDLE runthread = CreateRemoteThread(pidmodule, NULL, 0, (LPTHREAD_START_ROUTINE)loadaddress, vaeAddr, 0, NULL);
  57. if (runthread == NULL) {
  58. printf("CreateRemoteThread Error Code:%d\n", GetLastError());
  59. }
  60. printf("CreateRemoteThread Sucess\n");
  61. system("pause");
  62. return 0;
  63. }
  1. 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)

4. referers

精通Windows.API-函数、接口、编程实例.pdf