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. redis使用ssh密钥远控靶机

      首先说明一下我们的实验目的,我们这个实验需要利用一种公有密码,将公有密钥写入要攻击的服务器的redis数据库,然后使用我们自己的私钥进行远控肉鸡的操作. 实验环境:centos7(靶机,版本无太大 ...

  2. TensorFlow学习(1)-初识

    初识TensorFlow 一.术语潜知 深度学习:深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法. 深度学 ...

  3. IPFS挖矿必须要托管吗?

    IPFS 本质上只是一个人人使用的协议,而 Filecoin 是 IPFS 的激励层,大家平时说的 IPFS 挖矿,其实就是挖 Filecoin.而提到IPFS 就不得不说到矿机托管的问题. 点击了解 ...

  4. 面向对象进阶时,if语句写错位置

    这周blog我也不知道要写什么,因为这章我其实学得有点懵,前面那几天我纠结了好久代码,一直不知道原因错在哪里.后来经过询问老师才知道自己调用错了构造方法,相信也有跟我一样的新手会犯这个错误.我在创建关 ...

  5. python那些需要知道的事儿——内存泄漏

    啥,内存也会泄露?漏了咋补?我的内存会不会越漏越小?咋一听到内存泄漏,本喵的脑子蹦出无数想法,所以到底啥是内存泄漏! 一.垃圾回收机制(GC)机制 在理解内存泄漏之前,需要补充一个知识,即GC机制(也 ...

  6. 一文读懂MySql主从复制机制

    作为一个关系型数据库,MySQL内建地提供数据复制机制,这使得在使用时,可以基于其复制机制实现高可用架构等高级特性,从而使得MySQL无需借助额外的插件或其他工具就具备适用于生产环境.这是MySQL得 ...

  7. Github 镜像资源

    1.GitHub 镜像访问 这里提供两个最常用的镜像地址(别登录账号): https://github.com.cnpmjs.org https://hub.fastgit.org 也就是说上面的镜像 ...

  8. 滴水逆向初级-C语言(二)

    2.1.C语言的汇编表示 c语言代码 int plus(int x,int y) { return 0; } void main() { __asm { mov eax,eax } //调用函数 pl ...

  9. 【oracle学习笔记01】oracle architecture —— Memory Strucrure

    附图3: granule_size for each components 附图4:

  10. [Fundamental of Power Electronics]-PART I-2.稳态变换器原理分析-2.4 Cuk变换器实例

    2.4 Cuk 变换器 作为第二个示例,考虑图2.20(a)的变换器.该变换器执行类似于降压-升压变换器的直流转换功能:它可以增加或减小直流电压的幅值,并且可以反转极性.使用晶体管和二极管的实际实现如 ...