API Hook

ApiHook又叫做API劫持,也就是如果A程序调用了B.cll里面的C函数,我们可以做到当A调用C函数执行的时候,直接执行我们自己事先准备好的函数,之后我们在执行真正的C,当然我们可以不执行C或者更改C的参数等等,实现的核心思路就是:

mov eax, pNewAddr[/size][size=3] jmp eax

解释下具体原理:我们首先获取要劫持函数的地址,然后我们在自己组装一个数据结构,数据结构的内容是 执行汇编:把新函数地址拷到寄存器里,然后再jmp到新函数地址位置执行新函数,然后我们把自己组装这个数据结构拷贝到之前获取的需要劫持的函数地址指向的内存的位置,这样当我们再次调用该函数的时候,程序走到函数地址处发现是执行我们刚刚写好的汇编命令,直接jmp到了我们自己定义的函数地址的位置,也就相当于直接运行了我们自己写好的函数地址了,当然自己写的函数必须要和原函数参数和返回值一样,自己写的函数里面也可以调用原函数(达到过滤的目的),但是前提是调用之前要先关闭劫持,也就是把我们替换的内容给人家替换回去,执行完之后再次替换我们的地址,如果不替换回去我们就会进入无限递归了这个不解释,当然我们也可以修改参数什么的,给调用者进行一个“加工”。还有就是刚开始看的时候有一个地方不理解就是:DLL注入能成功的原理是,某些系统DLL里面的函数所有程序调用都会执行同一个地址,而APIHook中有一步是更改函数地址,但是如果我们更改了某些公用的函数地址,那么并不会影响其他的程序继续调用,这个地方小纠结了一会,后来弄清楚了,A加载了系统B.DLL获取里面的API函数C,
A2也同样加载并且获取了里面的API函数C2,C和C2是相等的(当然并不是所有都相等),但是我们在A程序里进行C函数的Hook,并没有影响A2的调用,原因是他们只是指向同一个地址不是就是同一个地址,可以理解成是中间有过度变量。我们修改的只是自己内存那部分”本分而已”,这样的话,我们想要Hook某个继承的某些API的话通常可以采取DLL注入的方式,DLL注入之前我总结过并且上传过相关的实现代码。这里不解释。然后就是在网上找到了一个写的不错的APIHook的代码,分享下(注意,下面代码是方便理解的,可以通过代码好好理解,但是实际开发不要用下面的代码,因为下面没考虑64位等其他问题,我平时开发常用的一个比较稳定的代码我上传在:http://download.csdn.net/detail/u013761036/9603063):

AdHookApi.h
#ifndef __ADHOOKAPI_H__
#define __ADHOOKAPI_H__
#include <windows.h>
#include <tchar.h>
#include <vector>
using namespace std; // class CAdAutoHookApi
class CAdHookApi;
class CAdAutoHookApi
{
public:
CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr);
virtual ~CAdAutoHookApi(); private:
CAdHookApi *m_pHookApi;
void *m_pAddr;
}; // class CAdAutoHook
class CAdHookApi
{
public:
CAdHookApi();
virtual ~CAdHookApi(); protected:
struct HookMap
{
HANDLE hProcess;
void *pOldAddr;
void *pNewAddr;
BYTE chOldCode[8];
BYTE chNewCode[8];
BOOL bHooked;
DWORD dwData;
};
public:
HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0);
HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0);
BOOL Remove(HANDLE hHook);
BOOL Begin(HANDLE hHook);
BOOL End(HANDLE hHook);
BOOL Begin2(void *pNewAddr);
BOOL End2(void *pNewAddr);
int BeginAll();
int EndAll();
int GetCount();
void *OldAddr2NewAddr(void *pOldAddr);
void *NewAddr2OldAddr(void *pNewAddr); public:
static BOOL VerifyAddress(void *pAddr, const BYTE *verifyData, DWORD verifySize); static BOOL PatchCode(void *pAddr, const BYTE *pCode, DWORD dwCode,
const BYTE *verifyData = NULL, DWORD verifySize = 0); protected:
CAdHookApi::HookMap *FromNewAddr(void *pNewAddr);
CAdHookApi::HookMap *FromOldAddr(void *pOldAddr);
BOOL HasHook(HANDLE hHook); protected:
vector<HookMap *> m_obHooks;
}; #endif // __ADHOOKAPI_H__ AdHookApi.cpp //#include "stdafx.h"
#include "AdHookApi.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <Windows.h>
#include "Common.h" static BOOL gUseAPI = TRUE; static BOOL WINAPI myReadMemory(HANDLE hProcess, LPVOID lpAddress, LPVOID lpBuffer, SIZE_T nSize)
{
BOOL bRet = FALSE;
DWORD dwOldProtect = 0;
bRet = VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect);
if(gUseAPI)
{
DWORD dwRead = 0;
bRet = ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead);
}
else
{
memcpy(lpBuffer, lpAddress, nSize);
}
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
assert(bRet);
return bRet;
} static BOOL WINAPI myWriteMemory(HANDLE hProcess, LPVOID lpAddress, LPCVOID lpBuffer, SIZE_T nSize)
{
BOOL bRet = FALSE;
DWORD dwOldProtect = 0;
bRet = VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect);
if(gUseAPI)
{
DWORD dwWrite = 0;
bRet = WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite);
}
else
{
memcpy(lpAddress, lpBuffer, nSize);
}
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
assert(bRet);
return bRet;
} // class CAdAutoHookApi
CAdAutoHookApi::CAdAutoHookApi(CAdHookApi *pHookApi, void *pAddr)
{
m_pHookApi = pHookApi;
m_pAddr = pAddr; assert(m_pHookApi != NULL); if(m_pHookApi != NULL)
{
m_pHookApi->End2(m_pAddr);
}
} CAdAutoHookApi::~CAdAutoHookApi()
{
if(m_pHookApi != NULL)
{
m_pHookApi->Begin2(m_pAddr);
}
} // class CAdHookApi
CAdHookApi::CAdHookApi()
{
} CAdHookApi::~CAdHookApi()
{
EndAll();
} BOOL CAdHookApi::VerifyAddress(void *pAddr, const BYTE *verifyData, DWORD verifySize)
{
BOOL isPassed = FALSE;
if((verifyData != NULL) && (verifySize > 0))
{
BYTE *addrData = new BYTE[verifySize];
if(myReadMemory(GetCurrentProcess(), pAddr, addrData, verifySize))
{
if(memcmp(addrData, verifyData, verifySize) == 0)
{
isPassed = TRUE;
}
}
delete []addrData;
}
else
{
isPassed = TRUE;
}
return isPassed;
} BOOL CAdHookApi::PatchCode(void *pAddr, const BYTE *pCode, DWORD dwCode,
const BYTE *verifyData, DWORD verifySize)
{
if(!VerifyAddress(pAddr, verifyData, verifySize))
{
return FALSE;
}
BOOL bRet = myWriteMemory(GetCurrentProcess(), pAddr, pCode, dwCode);
return bRet;
} HANDLE CAdHookApi::Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData)
{
HMODULE hModule = LoadLibrary(lpszModule);
if(hModule == NULL)
{
return NULL;
} void *pOldAddr = (void *)GetProcAddress(hModule, lpcFuncName);
if(pOldAddr == NULL)
{
return NULL;
} return Add(pOldAddr, pNewAddr, NULL, 0, dwData);
} HANDLE CAdHookApi::Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData, DWORD verifySize, DWORD dwData)
{
BOOL bRet = FALSE;
HookMap *pHook = new HookMap;
do
{
ZeroMemory(pHook, sizeof(HookMap)); pHook->hProcess = GetCurrentProcess(); pHook->pOldAddr = pOldAddr;
if(pHook->pOldAddr == NULL)
{
break ;
} DWORD dwRead = 8;
if((verifyData != NULL) && (verifySize > 0) && (verifySize > dwRead))
{
dwRead = verifySize;
}
BYTE *addrData = new BYTE[dwRead];
if(!myReadMemory(pHook->hProcess, pHook->pOldAddr, addrData, dwRead))
{
delete []addrData;
break ;
}
if((verifyData != NULL) && (verifySize > 0) && (memcmp(addrData, verifyData, verifySize) != 0))
{
delete []addrData;
break ;
}
memcpy(pHook->chOldCode, addrData, 8);
delete []addrData; DWORD dwTemp = (DWORD)pNewAddr;
pHook->pNewAddr = pNewAddr; // mov eax, pNewAddr
// jmp eax
pHook->chNewCode[0] = 0xB8;
memcpy(pHook->chNewCode + 1, &dwTemp, sizeof(DWORD));
pHook->chNewCode[5] = 0xFF;
pHook->chNewCode[6] = 0xE0; pHook->bHooked = FALSE; pHook->dwData = dwData; m_obHooks.push_back(pHook); bRet = TRUE;
}while(0);
if(!bRet)
{
delete pHook;
pHook = NULL;
} return (HANDLE)pHook;
} BOOL CAdHookApi::Remove(HANDLE hHook)
{
BOOL bRet = FALSE;
HookMap *pHook = (HookMap *)hHook;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp == pHook)
{
End((HANDLE)pTemp);
delete pHook;
m_obHooks.erase(m_obHooks.begin() + i);
bRet = TRUE;
break ;
}
} return bRet;
} BOOL CAdHookApi::Begin(HANDLE hHook)
{
if(!HasHook(hHook))
{
return FALSE;
}
HookMap *pHook = (HookMap *)hHook;
if(pHook->bHooked)
{
return TRUE;
}
DWORD dwWrite = 8;
BOOL bRet = myWriteMemory(pHook->hProcess, pHook->pOldAddr, pHook->chNewCode, dwWrite);
if(bRet)
{
pHook->bHooked = TRUE;
}
return bRet;
} BOOL CAdHookApi::End(HANDLE hHook)
{
if(!HasHook(hHook))
{
return FALSE;
}
HookMap *pHook = (HookMap *)hHook;
if(!pHook->bHooked)
{
return FALSE;
}
DWORD dwWrite = 8;
BOOL bRet = myWriteMemory(pHook->hProcess, pHook->pOldAddr, pHook->chOldCode, dwWrite);
if(bRet)
{
pHook->bHooked = FALSE;
}
return bRet;
} BOOL CAdHookApi::Begin2(void *pNewAddr)
{
HookMap *pHook = FromNewAddr(pNewAddr);
if(pHook == NULL)
{
return FALSE;
} return Begin((HANDLE)pHook);
} BOOL CAdHookApi::End2(void *pNewAddr)
{
HookMap *pHook = FromNewAddr(pNewAddr);
if(pHook == NULL)
{
return FALSE;
} return End((HANDLE)pHook);
} void *CAdHookApi::OldAddr2NewAddr(void *pOldAddr)
{
HookMap *pHook = FromOldAddr(pOldAddr);
if(pHook == NULL)
{
return NULL;
} return pHook->pNewAddr;
} void *CAdHookApi::NewAddr2OldAddr(void *pNewAddr)
{
HookMap *pHook = FromNewAddr(pNewAddr);
if(pHook == NULL)
{
return NULL;
} return pHook->pOldAddr;
} CAdHookApi::HookMap *CAdHookApi::FromNewAddr(void *pNewAddr)
{
HookMap *pHook = NULL;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp->pNewAddr == pNewAddr)
{
pHook = pTemp;
break ;
}
} return pHook;
} CAdHookApi::HookMap *CAdHookApi::FromOldAddr(void *pOldAddr)
{
HookMap *pHook = NULL;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp->pOldAddr == pOldAddr)
{
pHook = pTemp;
break ;
}
} return pHook;
} BOOL CAdHookApi::HasHook(HANDLE hHook)
{
BOOL bRet = FALSE;
HookMap *pHook = (HookMap *)hHook;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
if(pTemp == pHook)
{
bRet = TRUE;
break ;
}
} return bRet;
} int CAdHookApi::BeginAll()
{
int nRet = 0;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
BOOL bRet = Begin((HANDLE)pTemp);
if(bRet)
{
nRet ++;
}
} return nRet;
} int CAdHookApi::EndAll()
{
int nRet = 0;
for(int i = 0; i < (int)m_obHooks.size(); i ++)
{
HookMap *pTemp = m_obHooks[i];
BOOL bRet = End((HANDLE)pTemp);
delete pTemp;
if(bRet)
{
nRet ++;
}
}
m_obHooks.clear(); return nRet;
} int CAdHookApi::GetCount()
{
return (int)m_obHooks.size();
} User1 自己注入自己(测试用)
#include "stdafx.h"
#include "AdHookApi.h"
#include <windows.h>
using namespace std; static CAdHookApi AdHookApi; int WINAPI mYMessageBoxW( __in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType)
{
//如果是做过滤,记得先关闭掉当前的劫持,然后调用原API(给调用者看,当然这个地方也可以进行参数修改),
//然后再改成劫持的地址 也就是 end(a) do happythings begin(a)
MessageBoxA(NULL ,"B" ,"B" ,MB_OK);
return 0;
} int main()
{
AdHookApi.Add(_T("User32.dll") ,"MessageBoxW" ,mYMessageBoxW);
::MessageBoxW(NULL ,L"A" ,L"A" ,MB_OK);
AdHookApi.BeginAll();
::MessageBoxW(NULL ,L"A" ,L"A" ,MB_OK);
AdHookApi.EndAll();
::MessageBoxW(NULL ,L"A" ,L"A" ,MB_OK);
return 0;
} User2 DLL
#include "stdafx.h"
#include "ApiDebugger.h"
#include "AdHookApi.h"
#include <tlhelp32.h>
#include <wincrypt.h>
#include "Common.h" static const char * gCopyright = "ApiDebugger by CodeLive, email : dongfa@yeah.net";
static CAdHookApi gHooks; bool gEnableLogOutput = true; extern "C" APIDEBUGGER const char * ApiDebugger()
{
return gCopyright;
} /////////////////////////////////////////////////////////////////////////////// BOOL WINAPI my_IsDebuggerPresent(VOID)
{
return FALSE;
} int WINAPI my_CompareStringW(LCID Locale, DWORD dwCmpFlags, PCNZWCH lpString1, int cchCount1,
PCNZWCH lpString2,int cchCount2)
{
CAdAutoHookApi autoHook(&gHooks, my_CompareStringW);
logOutput(formatString("ApiDebugger - CompareStringW.\r\n"));
int ret = CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);
logOutput(formatString("ApiDebugger - CompareStringW(%S, %S).\r\n", lpString1, lpString2));
return ret;
} BOOL WINAPI my_CryptAcquireContextW(HCRYPTPROV *phProv, LPCWSTR szContainer, LPCWSTR szProvider,
DWORD dwProvType, DWORD dwFlags)
{
CAdAutoHookApi autoHook(&gHooks, my_CryptAcquireContextW);
BOOL ret = CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags);
logOutput(formatString("ApiDebugger - CryptAcquireContextW(0x%08X, %S, %S, 0x%08X, 0x%08X) : %S.\r\n",
(int)(*phProv),
(szContainer != NULL) ? szContainer : L"NULL",
(szProvider != NULL) ? szProvider : L"NULL",
dwProvType, dwFlags,
ret ? L"TRUE" : L"FALSE"
)); return ret;
} BOOL WINAPI my_CryptImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hPubKey,
DWORD dwFlags, HCRYPTKEY *phKey)
{
CAdAutoHookApi autoHook(&gHooks, my_CryptImportKey); BOOL ret = CryptImportKey(hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey); string hexData = toHexString((const char *)pbData, dwDataLen);
logOutput(formatString("ApiDebugger - CryptImportKey(0x%08X, %s, 0x%08X, 0x%08X, 0x%08X) : %S.\r\n",
(int)hProv, hexData.c_str(), (int)hPubKey, dwFlags, (int)(*phKey),
ret ? L"TRUE" : L"FALSE"
)); return ret;
} BOOL WINAPI my_CryptCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash)
{
CAdAutoHookApi autoHook(&gHooks, my_CryptCreateHash);
BOOL ret = CryptCreateHash(hProv, Algid, hKey, dwFlags, phHash);
logOutput(formatString("ApiDebugger - CryptCreateHash(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X) : %S.\r\n",
(int)hProv, (int)Algid, (int)hKey, dwFlags, (int)phHash,
ret ? L"TRUE" : L"FALSE"
));
return ret;
} BOOL WINAPI my_CryptHashData(HCRYPTHASH hHash, CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
{
CAdAutoHookApi autoHook(&gHooks, my_CryptHashData);
BOOL ret = CryptHashData(hHash, pbData, dwDataLen, dwFlags);
string hexData = toHexString((const char *)pbData, dwDataLen);
logOutput(formatString("ApiDebugger - CryptHashData(0x%08X, %s, 0x%08X) : %S.\r\n",
(int)hHash, hexData.c_str(), dwFlags,
ret ? L"TRUE" : L"FALSE"
));
return ret;
} BOOL WINAPI my_CryptDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey)
{
CAdAutoHookApi autoHook(&gHooks, my_CryptDeriveKey);
BOOL ret = CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey);
logOutput(formatString("ApiDebugger - CryptDeriveKey(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X) : %S.\r\n",
(int)hProv, (int)Algid, (int)hBaseData, dwFlags, (int)phKey,
ret ? L"TRUE" : L"FALSE"
));
return ret;
} BOOL WINAPI my_CryptDecrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags,
BYTE *pbData, DWORD *pdwDataLen)
{
CAdAutoHookApi autoHook(&gHooks, my_CryptDecrypt); string hexData1 = toHexString((const char *)pbData, *pdwDataLen);
writeDataToFile("CryptDec_IN.bin", pbData, *pdwDataLen);
BOOL ret = CryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
string hexData2 = toHexString((const char *)pbData, *pdwDataLen);
writeDataToFile("CryptDec_OUT.bin", pbData, *pdwDataLen); logOutput(formatString("ApiDebugger - CryptDecrypt(0x%08X, 0x%08X, %S, 0x%08X, %s=>%s) : %S.\r\n",
(int)hKey, (int)hHash, Final ? L"TRUE" : L"FALSE",
dwFlags, hexData1.c_str(), hexData2.c_str(),
ret ? L"TRUE" : L"FALSE"
));
return ret;
} typedef int (__cdecl *sub_4026B0_func)(BYTE *pbData); // 004026B0 ;
static int my_sub_4026B0(BYTE *pbData)
{
CAdAutoHookApi autoHook(&gHooks, my_sub_4026B0);
sub_4026B0_func sub_4026B0 = (sub_4026B0_func)(0x004026B0);
string hexData1 = toHexString((const char *)pbData, strlen((const char *)pbData));
int ret = sub_4026B0(pbData);
string hexData2 = toHexString((const char *)pbData, strlen((const char *)pbData)); logOutput(formatString("ApiDebugger - sub_4026B0(%s=>%s)",
hexData1.c_str(), hexData2.c_str())); return ret;
} /////////////////////////////////////////////////////////////////////////////// void ApiDebugferShutdown()
{
gHooks.EndAll(); logOutput("ApiDebugger Shutdown.\r\n");
} BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
// gHooks.Add(_T("KERNEL32.DLL"), "IsDebuggerPresent", my_IsDebuggerPresent);
// gHooks.Add(_T("KERNEL32.DLL"), "CompareStringW", my_CompareStringW);
gHooks.Add(_T("ADVAPI32.DLL"), "CryptAcquireContextW", my_CryptAcquireContextW);
gHooks.Add(_T("ADVAPI32.DLL"), "CryptImportKey", my_CryptImportKey);
gHooks.Add(_T("ADVAPI32.DLL"), "CryptCreateHash", my_CryptCreateHash);
gHooks.Add(_T("ADVAPI32.DLL"), "CryptHashData", my_CryptHashData);
gHooks.Add(_T("ADVAPI32.DLL"), "CryptDeriveKey", my_CryptDeriveKey);
gHooks.Add(_T("ADVAPI32.DLL"), "CryptDecrypt", my_CryptDecrypt);
/*
const BYTE verifyData[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x2C, 0x01, 0x00, 0x00 };
void *addr = (void *)0x004026B0;
if(gHooks.Add(addr, my_sub_4026B0, verifyData, sizeof(verifyData), 0) != NULL)
{
logOutput(formatString("ApiDebugger - hook sub_4026B0 ok.\r\n"));
}
else
{
logOutput(formatString("ApiDebugger - hook sub_4026B0 failed.\r\n"));
}
*/
gHooks.BeginAll(); logOutput(formatString("ApiDebugger - %s.\r\n", gCopyright));
logOutput("ApiDebugger Loaded.\r\n");
}
break ;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
{
}
break ;
case DLL_PROCESS_DETACH:
{
ApiDebugferShutdown();
logOutput("ApiDebugger Unloaded.\r\n");
}
break;
}
return TRUE;
}

windows-API劫持(API-HOOK)的更多相关文章

  1. Windows 8 动手实验系列教程 实验8:Windows应用商店API

    动手实验 实验 8: Windows应用商店API 2012年9月 简介 编写Windows应用商店应用最令人瞩目的理由之一是您可以方便地将它们发布到Windows应用商店.考虑到世界范围内目前有超过 ...

  2. Windows应用商店API

    Windows应用商店API 动手实验 实验 8: Windows应用商店API 2012年9月 简介 编写Windows应用商店应用最令人瞩目的理由之一是您可以方便地将它们发布到Windows应用商 ...

  3. Windows CE Notification API的使用方法

    1 引言      以Windows CE 为操作系统的掌上电脑(如PocketPC或HPC),除具备PC的功能外,还具备很强的自身控制能力.Windows CE API超越微软其他操作系统的 API ...

  4. Windows系统调用中API的3环部分(依据分析重写ReadProcessMemory函数)

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API的3环部分 一.R3环API分析的重 ...

  5. Windows系统调用中API从3环到0环(下)

     Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API从3环到0环(下) 如果对API在 ...

  6. Windows系统调用中API从3环到0环(上)

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API从3环到0环(上) 如果对API在三 ...

  7. 【转】asp.net Core 系列【二】—— 使用 ASP.NET Core 和 VS2017 for Windows 创建 Web API

    在本教程中,将生成用于管理“待办事项”列表的 Web API. 不会生成 UI. 概述 以下是将创建的 API: API 描述 请求正文 响应正文 GET /api/todo 获取所有待办事项 无 待 ...

  8. API & Web API

    The follow content refer refers to: Baidu Baike                  : https://baike.baidu.com/item/api/ ...

  9. Delphi常用API,API函数

    auxGetDevCaps API 获取附属设备容量 auxGetNumDevs API 返回附属设备数量 auxGetVolume API 获取当前卷设置 auxOutMessage API 向输出 ...

  10. 好的框架需要好的 API 设计 —— API 设计的六个原则

    说到框架设计,打心底都会觉得很大很宽泛,而 API 设计是框架设计中的重要组成部分.相比于有很多大佬都认可的面向对象的六大原则.23 种常见的设计模式来说,API 设计确实缺少行业公认的原则或者说设计 ...

随机推荐

  1. 关于主机不能访问虚拟机的web服务解决

    centos7默认并没有开启80端口,我们只有开启就行 [root@localhost sysconfig]# firewall-cmd --permanent --add-port=3032/tcp ...

  2. JVM实战调优(空格引发的服务异常)

    JVM实战调优 问题描述 某一个项目中有一个文字转语音的服务,使用的是科大讯飞的语音转换服务,需要调用三方服务.因其转换服务是一个耗时操作,官方给的demo使用的是 WebSocket 进行数据转换操 ...

  3. centos命令上传

    首先安装 lrzsz # yum -y install lrzsz 运行 rz 命令: 在弹出的窗口选择需要上传的文件,文件会被上传至对应的目录下 运行 sz file.name 在弹出的窗口选择保存 ...

  4. android分析之消息处理

    前序:每个APP对应一个进程,该进程内有一个ActivityThread的线程,称为主线程(即UI主线程),此外,还有其他线程,这个再论. android的消息系统分析. 每个Thread只对应一个L ...

  5. POJ_2452 Sticks Problem 【ST表 + 二分】

    一.题目 Sticks Problem 二.分析 对于$i$和$j$,并没有很好的方法能同时将他们两找到最优值,所以考虑固定左端点$i$. 固定左端点后,根据题意,$a[i]$是最小值,那么现在的问题 ...

  6. Python之内存泄漏和内存溢出

    预习知识:python之MRO和垃圾回收机制 一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题.对于一个用 python 实现的,长期运行的后台 ...

  7. Java并发编程之多线程

    线程 进程/线程/协程/管程 进程:操作系统会以进程为单位,分配系统资源(CPU时间片.内存等资源),是资源分配的最小单位 进程间通信(IPC): 管道(Pipe) 命名管道(FIFO) 消息队列(M ...

  8. P1085_不高兴的津津(JAVA语言)

    package 顺序与分支; /* * 题目描述 津津上初中了.妈妈认为津津应该更加用功学习,所以津津除了上学之外, 还要参加妈妈为她报名的各科复习班.另外每周妈妈还会送她去学习朗诵.舞蹈和钢琴. 但 ...

  9. PAT (Advanced Level) Practice 1002 A+B for Polynomials (25 分) 凌宸1642

    PAT (Advanced Level) Practice 1002 A+B for Polynomials (25 分) 凌宸1642 题目描述: This time, you are suppos ...

  10. 基于SageMath的数学网站——本科毕业开发项目

    1 绪论 1.1研究背景 我国是一个拥有15亿人口的大国.其中,据2017年的统计,全国共有大学生2600万左右.如此数量众多的大学生,都会有着学习基础数理课程的需求.而在高校的数学教学中,教授最多最 ...