常见Windows API(文件、注册表、服务、进程线程、DLL)

Windows Dll注入与API HOOK DLL注入: 1.      使用注册表注入dll HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit_DLLs AppInit_Dlls中设置待注入的dll绝对路径 LoadAppInit_Dlls值设为1 2.      使用Windows挂钩注入dll 需要使用SetWind 阅读详情

文件相关:

创建或打开文件:

HANDLE CreateFile(
  LPCSTR                lpFileName,                    //欲打开或创建的文件名,也可以是设备对象之类的被视为文件的相关对象
  DWORD                 dwDesiredAccess,               //对文件的访问模式,只读,只写,还可以进行位或同时指定两种模式
  DWORD                 dwShareMode,                    //打开文件的共享模式,文件是否允许其他进程进行操作,如果可以,可以指定操作的模式
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,           //表示安全属性可以指定返回的文件句柄是否可以被子进程继承,如果为NULL,表示无法被继承,否则需要将参数指向一个SECURITY_ATTRIBUTES的结构体,通常设为NULL
  DWORD                 dwCreationDisposition,           //在创建或打开的文件存在或不存在的时候该函数的处理方式
  DWORD                 dwFlagsAndAttributes,            //该参数用来指定新建文件的属性和对文件操作的方式
  HANDLE                hTemplateFile                    //文件模块句柄,系统会复制该文件模板的所有属性到当前创建的文件中
);

//该函数若执行成功,则返回文件句柄,若失败则返回INVALID_HANDLE_VALUE。具体失败的原因可以通过GetLastError()函数来得到,该函数即可以打开文件也可以创建文件,创建或打开文件之后要用CloseHandle()将文件句柄关闭 

eg: CreateFile(szTraget,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTES_NORMAL,NULL);

删除文件:

BOOL DeleteFile(
  LPCSTR lpFileName                //表示要删除的文件的文件名
);

读取文件内容:

BOOL ReadFile(
  HANDLE       hFile,                    //文件句柄,通常是CreateFile(返回的句柄)
  LPVOID       lpBuffer,                 //指向一个缓冲区,函数会将从文件中读出的数据保存在该缓冲区中
  DWORD        nNumberOfBytesToRead,     //要求读入的字节数,通常情况下是缓冲区的大小
  LPDWORD      lpNumberOfBytesRead,      //指向一个DWORD类型的变量,用于返回实际读入的字节数
  LPOVERLAPPED lpOverlapped              //一般设置位NULL
);

写入文件内容:

BOOL WriteFile(
  HANDLE       hFile,     
  LPCVOID      lpBuffer,
  DWORD        nNumberOfBytesToWrite,
  LPDWORD      lpNumberOfBytesWritten,
  LPOVERLAPPED lpOverlapped
);

//和ReadFile()函数的参数意义基本相同,所不同的是第二个参数,第二个参数仍指向同一个缓冲区,WriteFile()函数会将该缓冲区的内容进行写入。当用WriteFile()函数写文件时,写入的数据通常被Windows暂时保存在内部的高速缓存中,操作系统会定期进行盘写入,从而避免进行I/O操作影响执行效率。为了保证数据即时写入可以使用

FlushFileBuffers(
    HANDLE hFile //handle to file
)

//该函数会将指定文件句柄的缓冲区进行清空,使得Windows将缓冲区中的文件写入磁盘。该函数只有一个参数,即文件句柄。该文件句柄与ReadFile()和WriteFile()所使用的文件句柄相同

定位到文件的某个位置

DWORD SetFilePointer(
  HANDLE hFile,                    //进行文件操作时的文件句柄
  LONG   lDistanceToMove,          //指定要移动文件指针的距离
  PLONG  lpDistanceToMoveHigh,     //一个指向LONG型的指针,移动距离的高32位,一般为NULL
  DWORD  dwMoveMethod                //指针移动的起始位置。可以从文件开始位置进行移动,可以从当前文件位置开始移动,也可以从文件的末尾开始移动
);

获取本地所有逻辑驱动器

DWORD GetLogicalDriveStrings(
  DWORD  nBufferLength,                //表示lpBuffer的长度
  LPWSTR lpBuffer                      //表示接受本地逻辑驱动器名的缓冲区
);

获取驱动器类型

UINT GetDriveType(
  LPCSTR lpRootPathName        //驱动器名
);

创建目录

BOOL CreateDirectory(
  LPCSTR                lpPathName,                //创建目录的目录名称
  LPSECURITY_ATTRIBUTES lpSecurityAttributes       //安全属性,一般设置为NULL
);

移除目录

BOOL RemoveDirectory(
  LPCSTR lpPathName            //指定要移除目录的目录名
);

 

 

注册表相关:

基础知识:注册表是Windows系统管理和维护的配置较为复杂的信息数据库,它以树状形式存储信息,不同版本的Windows系统,其结构基本相同。由于各种软件为了满足自身的不同需求,对注册表中的信息进行读写,导致注册表中存在大量的冗余数据,因此有人戏称注册表是一个数据杂乱的“垃圾场”

注册表主要有这几项信息:根键、子键、键值项!键值项又包含:值名称,值类型和值

 

API:

打开注册表

LSTATUS RegOpenKeyEx(
  HKEY   hKey,                //指定一个父键句柄
  LPCSTR lpSubKey,            //指向一个字符串,用来表示要打开的子健名称
  DWORD  ulOptions,           //系统保留,必须指定为0值
  REGSAM samDesired,          //打开注册表的存取权限,为了方便对注册表的操作,通常使用KEY_ALL_ACCESS即可
  PHKEY  phkResult            //指向一个双子变量,用来接收打开的子键句柄
);


//如果函数执行成功,则返回ERROR_SUCCESS,并且在phkResult中保存返回打开子键的句柄
//所谓的打开注册表,就是打开注册表的某一个子键,然后进行操作

关闭注册表

LONG RegCloseKey{
    HKEY hKey        //是RegOpenKeyEx()的最后一个参数,即被打开的注册表句柄。
}

创建子键

LSTATUS RegCreateKeyEx(
  HKEY                        hKey,                    //用来指定父键句柄
  LPCSTR                      lpSubKey,                //指向一个字符串,用来表示要创建的子键名称
  DWORD                       Reserved,                //系统保留,必须指定为0值
  LPSTR                       lpClass,                 //子键类名,一般设置为NULL值
  DWORD                       dwOptions,               //创建子键时的选项,通常情况下使用REG_OPTION_NON_VOLATILE宏,表示创建的子键被创建到注册表文件中,而不是内存中
  REGSAM                      samDesired,               //打开注册表的存取权限,为了方便对注册表的操作,通常使用KEY_ALL_ACCESS即可
  const LPSECURITY_ATTRIBUTES lpSecurityAttributes,    //该参数指向一个SECURITY_ATTRIBUTES结构体用来指定键句柄的安全属性,这里一般使用NULL
  PHKEY                       phkResult,                //指向一个双子变量,用来接收打开的子键句柄
  LPDWORD                     lpdwDisposition            //一般设置为NULL
);


//如果函数执行成功,则返回ERROR_SUCCESS,并且在phkResult中保存返回创建子键的句柄。当需要创建的子键已经存在的时候,该函数起到与RegOpenKeyEx()函数同样的作用,那么打开系统注册表也可以使用RegCreateKeyEx()函数进行代替。不过该函数的参数比RegOpenKeyEx()多,所以不是很方便

删除子键

LSTATUS RegDeleteKey(
  HKEY   hKey,            //父键句柄
  LPCSTR lpSubKey         //要删除的子键名称
);

 读取键名称中的数据或者查询键名称的属性

LSTATUS RegQueryValueEx(
  HKEY    hKey,                //用来指定要读取的键值项所处的子键句柄
  LPCSTR  lpValueName,         //用来指定要读取的键值项的名称
  LPDWORD lpReserved,          //保留参数,必须为NULL
  LPDWORD lpType,              //接收返回的键值类型,如果不需要返回键值项类型,可以为NULL
  LPBYTE  lpData,              //指向一个缓冲区,用来接收返回的键值数据
  LPDWORD lpcbData             //在调用该函数时,这个参数用来指定缓冲区的长度;当函数返回时,该变量保存缓冲区实际接受到的长度
);

写入键值项

LSTATUS RegSetValueEx(
  HKEY       hKey,                //表示要写入键值项所处的子键句柄
  LPCSTR     lpValueName,         //指向定义键值项名称的字符串
  DWORD      Reserved,            //保留参数,必须为0
  DWORD      dwType,              //指出要写入的键值数据的类型
  const BYTE *lpData,             //指向要写入键值数据的缓冲区
  DWORD      cbData               //要写入键值数据的缓冲区长度
);

删除键值项

LONG RegDeleteValue{
    HKEY hKey;                    //指定要删除的句柄
    LOCTSTR lpValueName           //被删除键值项的名称
}

子键枚举

LSTATUS RegEnumKeyEx(
  HKEY      hKey,                    //指定被枚举的键句柄
  DWORD     dwIndex,                 //指定需要返回信息的子键索引编号
  LPSTR     lpName,                  //用户接收返回子键名称的缓冲区
  LPDWORD   lpcchName,               //调用函数前保存lpName指向缓冲区的长度,函数调用完成后,保存缓冲区实际接收到的数据长度
  LPDWORD   lpReserved,              //保留参数,必须为NULL
  LPSTR     lpClass,                 // 一般为NULL
  LPDWORD   lpcchClass,              //一般为NULL
  PFILETIME lpftLastWriteTime        //指向一个FILETIME的结构体,用于接收最后一次被写入的时间
);

键值枚举

LSTATUS RegEnumValue(
  HKEY    hKey,                    //指定被枚举的键句柄
  DWORD   dwIndex,                 //指定需要返回信息的键值索引编号
  LPSTR   lpValueName,             //用户接收返回键值名称的缓冲区
  LPDWORD lpcchValueName,          //在调用函数前,保存lpValueName指向的缓冲区的长度,调用完成后,保存缓冲区实际接收到的数据长度
  LPDWORD lpReserved,              //保留参数,必须为NULL
  LPDWORD lpType,                  //指向一个用于返回键值类型的双字变量
  LPBYTE  lpData,                  //用户接收返回值数据的缓冲区
  LPDWORD lpcbData                 //在调用该函数前,该参数保存lpData指向缓冲区的长度,该函数调用完成后,该参数保存缓冲区实际收到的数据长度
);

 

 

服务相关

打开服务管理器

SC_HANDLE OpenSCManager(
  LPCSTR lpMachineName,        //指向想要打开服务控制管理的主机,本机则设置为NULL
  LPCSTR lpDatabaseName,       //指向目标主机SCM数据库名字的字符串
  DWORD  dwDesiredAccess       //指定对SCM数据库的访问权限
);


//该函数调用成功,返回一个SCM句柄,否则返回NULL
//注:SCM是服务控制管理器的意思,他是系统服务的一个组成部分,跟开发的软件不是一个概念

关闭服务管理器

BOOL CloseServiceHandle{
    SC_HANDLE_hSCObject        
}


//该函数用来关闭由OpenSCManager()和OpenService()打开的句柄

服务的枚举

BOOL EnumServicesStatus(
  SC_HANDLE              hSCManager,                //OpenSCMamager()函数返回的句柄
  DWORD                  dwServiceType,             //指定枚举的服务类型,也就是自定义函数的参数
  DWORD                  dwServiceState,            //枚举指定状态的服务
  LPENUM_SERVICE_STATUSA lpServices,                //指向ENUM_SERVICE_STATUS类型的指针
  DWORD                  cbBufSize,                 //指定缓冲区的大小
  LPDWORD                pcbBytesNeeded,            //返回实际使用的内存空间大小
  LPDWORD                lpServicesReturned,        //返回枚举服务的个数
  LPDWORD                lpResumeHandle             //返回枚举是否成功
);


//ENUM_SERVICE_STATUS结构体
typedef struct _ENUM_SERVICE_STATUSA {
  LPSTR          lpServiceName;
  LPSTR          lpDisplayName;
  SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUSA, *LPENUM_SERVICE_STATUSA;


//SERVICE_STATUS结构体
typedef struct _SERVICE_STATUS {
  DWORD dwServiceType;
  DWORD dwCurrentState;
  DWORD dwControlsAccepted;
  DWORD dwWin32ExitCode;
  DWORD dwServiceSpecificExitCode;
  DWORD dwCheckPoint;
  DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;

打开服务

SC_HANDLE OpenService(
  SC_HANDLE hSCManager,            //指向由OpenSCManager()函数打开的服务句柄
  LPCSTR    lpServiceName,         //指定要打开的服务的名称
  DWORD     dwDesiredAccess        //对要打开服务的访问权限,为了方便可以用SC_MANAGER_ALL_ACCESS
);

启动服务

BOOL StartService(
  SC_HANDLE hService,                    //指定要启动服务的句柄,该句柄由OpenService()返回
  DWORD     dwNumServiceArgs,            //指定启动服务所需的参数个数
  LPCSTR    *lpServiceArgVectors         //指定启动服务的参数
);

停止服务

BOOL ControlService(
  SC_HANDLE        hService,            //指定一个由OpenService()打开的服务句柄
  DWORD            dwControl,           //指定要发送的控制码
  LPSERVICE_STATUS lpServiceStatus      //返回服务的状态
);

//这个函数可以对服务进行多种控制操作,每种控制操作对应一种控制码,当要停止服务时,使用的控制码为SERVICE_CONTROL_STOP

 

进程线程相关

创建进程

BOOL CreateProcess(
  LPCSTR                lpApplicationName,        //指定可执行文件的文件名
  LPSTR                 lpCommandLine,            //指定相传给命令行的参数
  LPSECURITY_ATTRIBUTES lpProcessAttributes,      //进程安全属性,通常为NULL。表示默认安全属性
  LPSECURITY_ATTRIBUTES lpThreadAttributes,       //线程安全属性,通常为NULL,表示默认安全属性
  BOOL                  bInheritHandles,          //指定当前进程中的科技城句柄是否被新进程继承
  DWORD                 dwCreationFlags,          //指定新进程的优先级以及其他创建标志,该参数一般情况下可为0
  LPVOID                lpEnvironment,            //指定新进程的环境变量,通常这里指定为NULL值
  LPCSTR                lpCurrentDirectory,       //指定新进程使用的当前目录值
  LPSTARTUPINFOA        lpStartupInfo,            //指向STATUPINFO结构体的指针,该结构体的定义如下:
  LPPROCESS_INFORMATION lpProcessInformation      //指向PROCESS_INFORMATION结构体的指针,该结构体用于返回新进程和主线程的相关信息,定义如下:
);

typedef struct _STARTUPINFOA {
  DWORD  cb;
  LPSTR  lpReserved;
  LPSTR  lpDesktop;
  LPSTR  lpTitle;
  DWORD  dwX;
  DWORD  dwY;
  DWORD  dwXSize;
  DWORD  dwYSize;
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;
  HANDLE hStdOutput;
  HANDLE hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;

得到窗口线程PID

DWORD GetWindowThreadProcessId(
  HWND    hWnd,                     //窗口句柄,代码中的窗口句柄是由FindWindow()函数获取的
  LPDWORD lpdwProcessId             //该参数是一个指向DWORD类型的指针,用户返回窗口句柄所对应的进程ID
);

通过进程ID得到进程句柄

HANDLE OpenProcess(
  DWORD dwDesiredAccess,        //打开进程欲获得的访问权限,该参数为了方便,可以始终为PROCESS_ALL_ACCESS
  BOOL  bInheritHandle,         //指定获得的句柄是否可以被继承,,一般选择不继承,为FALSE
  DWORD dwProcessId             //指定想要打开的进程ID号,该进程ID号是由GetWindowThreadProcessID()所得的
);

通过进程句柄类结束进程

BOOL TerminateProcess(
  HANDLE hProcess,            //想要结束的进程句柄,该句柄由OpenProcess()函数得到
  UINT   uExitCode            //进程的退出码,通常为0
);

进程枚举相关的函数

#include <Tlhelp32.h>
HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,                   //指明要建立快照的类型
  DWORD th32ProcessID              //根据dwFlags的参数的不同而不同,如果枚举的是系统中的进程或系统中的线程,该参数为NULL,如果枚举的是进程中加载的DLL的话,那么该进程参数是进程ID
);
//该函数返回一个快照的句柄,并提供给枚举函数使用

BOOL Process32First(
  HANDLE           hSnapshot,      //该参数为CreateToolhelp32Snapshot()返回的句柄
  LPPROCESSENTRY32 lppe            //该参数为指向PROCESSENTRY32结构体的指针,该结构体的定义如下
);
typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;
  DWORD     cntUsage;
  DWORD     th32ProcessID;
  ULONG_PTR th32DefaultHeapID;
  DWORD     th32ModuleID;
  DWORD     cntThreads;
  DWORD     th32ParentProcessID;
  LONG      pcPriClassBase;
  DWORD     dwFlags;
  CHAR      szExeFile[MAX_PATH];
} PROCESSENTRY32;
//在使用该结构体时,要对结构体中的程序变量dwSize进行复制。该变量保存PROCESSENTRY32结构体的大小

BOOL Process32Next(
  HANDLE           hSnapshot,    
  LPPROCESSENTRY32 lppe
);
//枚举进程中加载的DLL文件和枚举系统中得到线程都与以上两个函数类似,所不同的是使用FIRST和NEXT的第二个参数指向的结构体不同
//对于dll文件来说,指向的结构体如下
typedef struct tagMODULEENTRY32 {
  DWORD   dwSize;
  DWORD   th32ModuleID;
  DWORD   th32ProcessID;
  DWORD   GlblcntUsage;
  DWORD   ProccntUsage;
  BYTE    *modBaseAddr;
  DWORD   modBaseSize;
  HMODULE hModule;
  char    szModule[MAX_MODULE_NAME32 + 1];
  char    szExePath[MAX_PATH];
} MODULEENTRY32;
//对于系统中的线程来说,指向的结构体定义如下
typedef struct tagTHREADENTRY32 {
  DWORD dwSize;
  DWORD cntUsage;
  DWORD th32ThreadID;
  DWORD th32OwnerProcessID;
  LONG  tpBasePri;
  LONG  tpDeltaPri;
  DWORD dwFlags;
} THREADENTRY32; 

//有些权限不足的进程无法被枚举出来,进程的权限不够,解决方法是将进程的权限提升至"SeDebugPrivilege"
//调整进程权限的步骤如下
//1、使用OpenProcessToken()函数打开当前进程的访问令牌
//2、使用LookupPrivilegeValue()函数取得描述权限的LUID
//3、使用AdjustTokenPrivileges()函数调整访问令牌的权限
//调整权限的代码如下:

void CManagerProcessDlg::DebugPrivilege()
{
    HANDLE hToken = NULL;
    BOOL bRet  = OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken);
    if(bRet == TRUE)
    {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount = 1;
        LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(hToken,FALSE,&TP,sizeof(tp),NULL,NULL);
        CloseHandle(hToken);    
}
}

暂停线程

DWORD SuspendThread( HANDLE hThread );
//该函数只有一个参数,是要暂停线程的句柄

获得线程句柄

HANDLE OpenThread(
  DWORD dwDesiredAccess,            //打开线程欲获得的访问权限,为了方便,可以始终为PROCESS_ALL_ACCESS
  BOOL  bInheritHandle,             //指定获取的句柄是否可以继承,一般选择不继承,传FALSE
  DWORD dwThreadId                  //线程ID
);

恢复暂停的线程

DWORD ResumeThread(
  HANDLE hThread            //线程句柄
);

多线程相关:

线程创建:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,        //指明创建线程的安全属性,为指向SCEURITY_ATTRIBUTES结构的指针,一般为NULL
  SIZE_T                  dwStackSize,               //指定线程使用的缺省的堆栈大小,如果为NULL,则与进程主线程栈相同
  LPTHREAD_START_ROUTINE  lpStartAddress,            //指定线程函数,线程即从该函数的入口处开始运行,函数返回时意味着线程终止运行,该函数属于一个回调函数
  __drv_aliasesMem LPVOID lpParameter,                //该参数表示传递给线程函数的一个参数,可以是指向任意数据类型的指针
  DWORD                   dwCreationFlags,            //指明创建线程后的线程状态,需要立即执行设置为0,让线程处于暂停状态,那么设置为CREATE_SUSPENDED
  LPDWORD                 lpThreadId                  //该参数用于返回新创建的线程ID
);

//如果函数创建成功,该函数返回线程的而句柄,否则返回NULL。线程的句柄需要通过CloseHandle()进行关闭,以便释放资源

主线程等待新线程的完成才执行

DWORD WaitForSingleObject(
  HANDLE hHandle,                //要等待的对象句柄
  DWORD  dwMilliseconds          //指定等待超时的毫秒数,如果为0,则立即返回,如果为INFINITE,则表示一直等待线程函数的返回
);

#define INFINITE 0xFFFFFFFF

//如果函数失败,返回WAIT_FAILED;富国等待的对象编程激发状态,则返回WAIT_OBJECT_0。如果等待对象编程激发状态之前,等待时间结束了,将返回WAIT_TIMEOUT

如果需要等待多个线程完成状态的话,需要用到

DWORD WaitForMultipleObjects(
  DWORD        nCount,                //用于指明想要让函数等待的线程的数量,这个值在1和MAXIMUM_WAIT_OBJECTS之间
  const HANDLE *lpHandles,            //指向等待线程句柄的数组指针
  BOOL         bWaitAll,              //该参数表示是否等待全部线程的状态完成,如果设置为TRUE,则等待全部
  DWORD        dwMilliseconds         //等待超时的毫秒数,如果为0,则立即返回,如果为INFINITE,则表示一直等待线程函数的返回
);

临界区相关的函数

void InitializeCritcalSection{
    LPCRITICAL_SECTION lpCriticalSection
}
//初始化临界区对象

void EnterCritcalSection{
    LPCRITICAL_SECTION lpCriticalSection
}
//进入临界区

void LeaveCritcalSection{
    LPCRITICAL_SECTION lpCriticalSection
}
//离开临界区

void DeleteCritcalSection{
    LPCRITICAL_SECTION lpCriticalSection
}
//删除临界区

//注:临界区对象只能用于多线程互斥

 

DLL相关

加载DLL文件

HMODULE LoadLibrary(
  LPCSTR lpLibFileName            //要加载的DLL的文件名。该函数调用成功,则返回一个模块句柄
);

得到进程地址

FARPROC GetProcAddress(
  HMODULE hModule,            //该参数是模块句柄,通常通过LoadLibrary()和GetModuleHandle()函数获得
  LPCSTR  lpProcName          //指定要获得函数地址的函数名称
);

//函数调用成功,则返回lpProcName指向的函数名的函数地址

DLL远程注入

创建远程线程

HANDLE CreateRemoteThread(
  HANDLE                 hProcess,                       //指定要创建线程的进程句柄,其他参数和CreateThread()相同
  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  SIZE_T                 dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID                 lpParameter,
  DWORD                  dwCreationFlags,
  LPDWORD                lpThreadId
);

将欲加载的DLL文件完成路径写入目标进程中

BOOL WriteProcessMemory(
  HANDLE  hProcess,                    //指定进程的进程句柄
  LPVOID  lpBaseAddress,               //指定写入目标进程内存的起始地址
  LPCVOID lpBuffer,                    //写入目标进程内存的缓冲区起始地址
  SIZE_T  nSize,                       //指定写入目标内存中的缓冲区长度
  SIZE_T  *lpNumberOfBytesWritten      //用于接收实际写入内容的长度
);

//该函数的功能是把lpBuffer中的内容写到进程句柄是hProcess进程的lpBaseAddress地址处,写入长度为nSize
//注:该函数功能非常强大,比如在破解方面,用该函数可以实现一个“内存补丁;在开发方面”,该函数可以用于修改目标进程中指定的值(比如游戏修改器可以修改游戏中的钱)

在目标进程中申请内存

LPVOID VirtualAllocEx(
  HANDLE hProcess,                //指定进程的进程句柄
  LPVOID lpAddress,               //指定在目标进程中申请内存的起始地址
  SIZE_T dwSize,                  //在目标进程中申请内存的长度
  DWORD  flAllocationType,        //指定申请内存的状态类型
  DWORD  flProtect                //指定申请内存的属性
);

//该函数的返回值实在目标进程申请到的内存块的起始地址

DLL卸载

BOOL FreeLibrary(
  HMODULE hLibModule            //要卸载模块的句柄
);

 

HOOK API——Windows核心编程 第22章 插入DLL和挂接API学习笔记 介绍:HOOK API是指截获特定进程或系统对某个API函数的调用,使得API的执行流程转向指定的代码。Windows下的应用程序都建立在API函数至上,所以截获API是一项相当有用的技术,它使得用户有机会干预其它应用程序的程序流程。最常用的一种挂钩API的方法是改变目标进程中调用API函数的代码,使得它们对API的调用变为对用户自定义函数的调用。HOOK API和HOOK技术完全不同。尽 阅读详情

相关推荐

DLL注入实战:3招轻松攻破进程

本文提供了Windows环境下DLL注入的实战指南,包含三种可直接上手的实现方案。通过远程线程注入(最通用)、进程创建时注入和注册表注入三种方式,详细介绍了操作步骤和完整代码实现。重点阐述了DLL加载原理、权限要求等前置知识,并给出位数一致性、权限问题等关键注意事项。文章还推荐了ProcessExplorer等辅助工具,帮助验证注入效果。特别强调实际应用中需遵守法律法规,建议从远程线程注入方案开始练习。所有方案都经过实践验证,确保新手也能快速掌握这项技术。

m0_60781580的博客 1057

实验四 理解程序、进程、线程及利用Windows注册表完成相应操作

实验目的理解程序、进程、线程的含义以及关系。2、学习和掌握利用Windows注册表完成任意程序的多种自启动。3、学习和掌握利用Windows注册表修改常见的文件类型的关联方式。4、学习和掌握利用Windows注册表完成镜像劫持操作。实验环境操作环境:Windows7实验工具:cmd、regedit实验原理通过自启动机制,应用程序、内核驱动或系统服务在Windows系统启动时能自行完成自身启动。病毒除利用注册表完成自启动之外,还可利用文件类型关联程序完成隐匿自启动。新建一个以杀毒软件主程序命名的项,例如Win

m0_56948411的博客 1044

《Windows核心编程》读书笔记二十二章 DLL注入和API拦截

第22章  DLL注入和API拦截 本章内容 22.1 DLL注入的一个例子 22.2 使用注册表来注入DLL 22.3 使用Windows挂钩来注入DLL 22.4 使用远程线程来注入DLL 22.5 使用木马DLL来注入DLL 22.6 把DLL作为调试器来注入 22.7 使用CreateProcess来注入代码 22.8 API拦截的例子 通常在操作系统中

sesiria的博客 2743

CreatProcess - WINDOWS API 第一弹 进程相关

CreatProcess

Bobowen的博客 1397

通过Windows Service启动外部程序Cjwdev.WindowsApi.dll

window服务启动其他程序,解决隐藏看不见的问题。 使用方法见: https://blog.youkuaiyun.com/dqs78833488/article/details/52806226?locationNum=3&fps=1

C#写Windows服务调用EXE,界面出不来,需要调用Cjwdev.WindowsApi.dll

最近项目中需要用C#写Windows服务调用EXE,最终进程什么的都有了,就是界面出不来,查看相关的资料,需要调用Cjwdev.WindowsApi.dll,但是这个在网上可不好下载,所以就拿来分享了。

关于注册表组件线程设置

技术总监问我,在注册表关于组件多线程设置,在服务器找到已注册dll发现ThreadingModel键值,真不知什么意思,以下文章我看了真不懂,反正发现值是free,是支持多线程,以下备忘留用。       转自http://blog.sina.com.cn/s/blog_56dee71a0100ngrv.html -------------------------------------

第四类人 3386

API动态库文件dll.zip

API动态链接库文件api-ms-win-core-console-l1-1-0.dll api-ms-win-core-file-l1-1-0.dll api-ms-win-crt-convert-l1-1-0.dll等

浅谈 Windows API 编程

原文地址:http://blog.sina.com.cn/s/blog_46d85b2a01010qpt.html http://blog.sina.com.cn/s/articlelist_1188584234_0_1.html WinSDK 是编程中的传统难点,曾经听有一个技术不是很好的朋友乱说什么给你 API 谁都会用,其实并非那么简单,个人写的WinAPI 程序也不少了,其...

freeking101的博客 9906

Cjwdev.WindowsApi win7服务启动外部程序

Win7下C#通过Windows Service启动外部程序时要用到的一个第三方动态库。 官方网站上下载稍有点费劲,下载下来与大家免费分享。

多线程同步演示(采用CreateThread()和WaitForMultipleObjects()函数)

采用多线程技术,使用CreateThread WaitForMultipleObjects函数等,实现了5个人赛跑比赛的模拟,并统计比赛结果。是一个比较好的多线程的演示。

Windows服务启动进程Cjwdev.WindowsApi.dll 的下载

windows 启动后台进程

dream_follower的博客 4303

什么是无人机电源管理模块?电源管理模块有什么用处?

我来描述一下我的问题情景,电源管理模块的定义是,这里给出这个PX4官方对于电源管理模块的一些介绍,补充一下锂电池的放电原理大家就可以更好理解为什么需要电源管理模块

HRWVY0725的博客 2272

windows DLL注入之注册表注入

windows下的注入之注册表注入: 1.概念介绍: 注入与Hook:注入与hook经常被人们混淆,其实注入和hook是两种windows下的编程技术(当然,其他平台也有相关的技术),由于在安全编程中,两项技术经常被同时结合起来使用,所以常常导入混淆。今天我们就谈谈windows下的注入技术。 1.1 Hook: hook 的中文名叫钩子,hook 是程序设计中最为灵活多变的技巧之一,hook对指...

qq_33168924的博客 2482

物联网技术(AIR780E cat1-4G模块+小程序+腾讯云MQTT)驱动的智能井盖系统设计(连载01)

终端设备采用AIR780E模块作为主控器,电子模块有三轴加速度传感器、可燃气体传感器,AIR780E模块(4G模块)通过MQTT通信协议进行数据打包上传至EMQX服务器,在EMQX服务器中,用户可以自行订阅主题和发布主题,小程序通过MQTT通信协议订阅EMQX服务器的主题,服务器通过接收到硬件发布的数据,转发到微信小程序。

leida_3669的博客 2215

n8n实战:动态报表生成与企业微信自动化推送

本文详细介绍了如何利用n8n实现动态报表生成与企业微信自动化推送的全流程。通过配置n8n Form触发器、智能报表生成核心逻辑以及企业微信Webhook推送,帮助企业大幅提升数据收集与报表推送效率,实现从数据录入到报表推送的全自动化处理。

weixin_29267307的博客 304

ProcessMonitor实现进程文件和注册表监控

对于文件、网络等监控亦是如此,进程的启动和执行离不开对于文件的读写,,相信很多人都碰到DLL文件找不到但是却又不知道DLL放在哪个路径的问题,而这个工具能捕获进程的所有文件读写信息,正好解决了这种问题。一般我们监控指定进程可以使用processName和PID,以谷歌浏览器为例,它的进程名是chrome.exe,那么就可以根据 "processName is chrome.exe"来监控所有的chrome.exe进程了,因为chrome.exe一般是多进程模式,如果定位单个进程,那么就需要指定PID了。

weixin_38526093的博客 8698

从 SAP ABAP 到 S/4HANA,SAML 2.0 单点登录到底是怎么跑起来的

在很多 SAP 项目里,SSO 不是一个锦上添花的功能,而是系统能不能顺利上线的基本门槛。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1048

Windows核心编程:DLL注入和API拦截

 作者:shenzi链接:http://blog.youkuaiyun.com/shenzi Windows核心编程:DLL注入和API拦截     在Windows中,每个进程有自己的私有地址空间。当我们用指针来引用内存的时候,指针的值表示的是进程自己的地址空间中的一个内存地址。进程不能创建一个指针来引用属于其它进程的内存。

shenzi的天空 1万+

基于CNN-LSTM融合模型的环卫车动态称重算法研究:从频率感知到精准质量估计

摘要: 针对环卫车辆动态称重需求,本研究提出一种基于CNN-LSTM融合网络的频率分析方法。通过在实验室构建振动频率采集系统,获取不同载重下的结构响应数据,经MATLAB进行信号处理和特征提取后,建立频率-质量的非线性映射模型。实验表明,该算法在静态和模拟动态场景下平均绝对误差小于1.5%,显著优于传统方法,为环卫车智能化管理提供了高精度实时称重方案。 关键词: 动态称重;深度学习;频率分析;CNN-LSTM;MATLAB。

AI的内部世界的博客 374

MounRiver Studio(MRS)使用技巧:添加头文件目录;增加代码分组

MounRiver Studio(MRS)使用技巧:添加头文件目录

cheng___yi的博客 1808

Windows下Dll注入与API拦截

让我们来看一个例子。当这个通知被处理时,U s e r 3 2 . d l l便检索保存的这个关键字中的值,并且为字符串中指定的每个D L L调用L o a d L i b r a r y函数。当每个库被加载时,便调用与该库相关的D l l M a i n函数,其f d w R e a s o n的值是D L L _ P R O C E S S _ AT TA C H,这样,每个库就能够对自己进行初始化。在理想的情况下,你的D L L只应该映射到需要的进程中,同时,它应该以尽可能少的时间映射到这些进程中。

qiexinyueaifei的博客 1597

RT-DETR改进策略【损失函数篇】| 通过辅助边界框计算IoU提升检测效果(Inner_GIoU、Inner_DIoU、Inner_CIoU、Inner_EIoU、Inner_SIoU)

为了弥补现有 IoU 损失在不同检测任务中泛化性弱和收敛速度慢的问题,·Inner-IoU·通过引入比例因子 “ratio” 来控制辅助边界框的尺度大小,利用不同尺度的辅助边界框来计算损失,从而加速边界框回归过程。

Limiiiing的博客 1962

[笔记]Windows核心编程《二十二》注入DLL和拦截API

文章目录前言一、插入DLL:一个例子二、使用注册表来插入DLL三、使用Windows挂钩来插入DLL四、使用远程线程来插入DLL4.1 Inject Library示例应用程序4.2 Image Walk DLL五、使用特洛伊DLL来插入DLL六、将DLL作为调试程序来插入七、用Windows 98上的内存映射文件插入代码八、用CreateProcess插入代码九、挂接A P I的一个示例9.1 通过改写代码来挂接API、9.2 通过操作模块的输入节来挂接API9.3 LastMsgBoxInfo示例应用程

二次元怪兽的博客 2039

基于DPCNN实现电商情感分析任务

下载链接项目中使用的模型是DPCNN,在模型中我们定义了三个组件,分别是embedding层,卷积层和全连接层。Embedding层:将每个词生成对应的嵌入向量,就是利用一个连续型向量来表示每个词卷积层:提取语句中的语义信息Linear层:将结果映射成2大小用于二分类,即正反面的概率。

优快云 精品推荐 1629

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

逆向工程核心原理——DLL注入——创建远程线程

什么是DLL注入? dll注入是一种将Windows动态链接库注入到目标进程中的技术,具体的说,就是将dll文件加载到一个进程的虚拟地址空间中。对某个进程进行dll注入,也就意味着dll模块与该进程共用一个进程空间,则这个dll文件就有了操纵这个进程空间的能力,以达到执行dll模块中的代码修改进程数据的能力。dll注入技术在逆向工程,病毒,外挂,调试等技术领域都有广泛的应用,它也是Windows API hook技术的基础。 改善功能与修复Bug改善功能与修复Bug DLL注入技术可用于改善功.

weixin_46601374的博客 3759

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

上一篇: pwn_note
下一篇: 在 Nexus 5X 上安装 NetHunter
fa1lr4in
博客等级 码龄9年 64粉丝 79原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值