其他
为无源码的数据批量处理软件添加功能
一
软件简介
二
需求
三
思路
总体流程
四
具体步骤
添加导入表项
IAT hook实现
{
if (szModuleName == NULL || szFuncName == NULL || NewFuncAddress == NULL)
{
return -1;
}
int ImageBase = (int)GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
//此处暂时不考虑64位的情况,所以直接定义32位的选项头
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader;
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != 0x5A4D) {
return -1;
}
//获取NT头
pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + ImageBase);
if (pNtHeader->Signature != 0x00004550) {
return -1;
}
//获取选项头
pOptionalHeader = &pNtHeader->OptionalHeader;
IMAGE_DATA_DIRECTORY DataDirectoryImport = pOptionalHeader->DataDirectory[1];
//获取导入表地址
PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)(DataDirectoryImport.VirtualAddress + ImageBase);
//获取需要hook的函数所在的模块对应的模块句柄
HMODULE hModule = GetModuleHandle(szModuleName);
if (hModule == NULL)
{
return -1;
}
//获取原函数的位置
int pFunc = (int)GetProcAddress(hModule, szFuncName);
if (pFunc == NULL)
{
return -1;
}
while (pImportDirectory->OriginalFirstThunk != 0)
{
char* szDllName = (char*)(pImportDirectory->Name + ImageBase);
if (!strcmp(szDllName, szModuleName))
{
DWORD* pAddress = (DWORD*)(pImportDirectory->FirstThunk + ImageBase);
while (*pAddress != 0)
{
if (*pAddress == pFunc)
{
DWORD OldProtect = 0;
//修改内存属性,使其可写
VirtualProtect(pAddress, 0x1000, PAGE_EXECUTE_READWRITE, &OldProtect);
*pAddress = (DWORD)NewFuncAddress;
//改回内存属性,防止兼容性问题
VirtualProtect(pAddress, 0x1000, OldProtect, &OldProtect);
break;
}
pAddress++;
}
break;
}
pImportDirectory++;
}
return 0;
}
修改窗口过程函数
BOOL IsModify = FALSE;
BOOL WINAPI MyGetMessageA(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
{
if (!IsModify)
{
char* szWindowNames[3] = {
"全能字符串批量替换机7.0 无限制版(替换/查找/抽取/改名)", //Chinese(S)
"つ匡ゅンい猔種称", //Chinese(T)
"Super Replacer(Replace/Find/extract/rename)" //English
};
HWND hWnd = NULL;
bool IsMyWindow = false;
//查找窗口
for (int i = 0; hWnd == NULL && i < 3; i++)
{
hWnd = ::FindWindow(NULL, szWindowNames[i]);
}
if (hWnd != NULL)
{
DWORD ProcessId = 0;
//判断窗口是否属于本进程
if (GetWindowThreadProcessId(hWnd, &ProcessId) != 0)
{
DWORD MyProcessId = GetCurrentProcessId();
if (MyProcessId == ProcessId)
{
IsMyWindow = true;
}
}
}
if (IsMyWindow)
{
g_Wnd = hWnd;
//判断窗口字符集
BOOL nRet = IsWindowUnicode(hWnd);
//修改窗口过程函数
if (nRet)
{
g_OldWindowProc = (PFN)SetWindowLongW(hWnd, GWL_WNDPROC, (int)WindowProc);
}
else
{
g_OldWindowProc = (PFN)SetWindowLongA(hWnd, GWL_WNDPROC, (int)WindowProc);
}
IsModify = TRUE;
}
}
//调用原先被hook的函数
return GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}
窗口过程函数功能实现
//旧的窗口过程函数
PFN g_OldWindowProc = NULL;
//记录过程函数是否已经被修改
BOOL IsModify = FALSE;
HWND g_Wnd;
int g_nClickedColumn;
CListCtrl* g_pListCtrl;
bool IsReverseOrder = false;
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CListCtrl* pListCtrl = g_pListCtrl;
CString strItem1 = pListCtrl->GetItemText(lParam1, g_nClickedColumn);
CString strItem2 = pListCtrl->GetItemText(lParam2, g_nClickedColumn);
int nItem1 = StrToInt(strItem1);
int nItem2 = StrToInt(strItem2);
int ret = nItem2 - nItem1;
if (!IsReverseOrder)
{
ret = 0 - ret;
}
return ret;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_NOTIFY)
{
NMHDR* pNMHDR = (NMHDR*)lParam;
if (pNMHDR->code == LVN_COLUMNCLICK)
{
NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
if (pNMLV->hdr.idFrom == ID_LISTCTRL) // 检查控件ID,确保是你要处理的列表控件
{
HWND hListCtrl = ::GetDlgItem(g_Wnd, ID_LISTCTRL);
CListCtrl* pListCtrl = reinterpret_cast<CListCtrl*>(CListCtrl::FromHandle(hListCtrl));
g_pListCtrl = pListCtrl;
g_nClickedColumn = pNMLV->iSubItem;
if (g_nClickedColumn == 2)
{
//将每一项进行排序
pListCtrl->SortItemsEx(CompareFunc, (LPARAM)pListCtrl);
//再次点击的话,就将顺序颠倒
IsReverseOrder = !IsReverseOrder;
}
return TRUE;
}
}
}
return g_OldWindowProc(hwnd, uMsg, wParam, lParam);
}
五
总结
看雪ID:UltraTC
https://bbs.kanxue.com/user-home-980660.htm
# 往期推荐
2、Nep CTF password:rc4和换表base64算法分析
6、【NKCTF】babyHeap-Off by one&Tcache Attack
球分享
球点赞
球在看
点击阅读原文查看更多