├── CodeSeg.cpp ├── CodeSeg.h ├── DetourInfo.cpp ├── DetourInfo.h ├── Disasm.cpp ├── DumpInfoDlg.cpp ├── DumpInfoDlg.h ├── EasySize.h ├── HookInfoDlg.cpp ├── HookInfoDlg.h ├── HookRepairer.aps ├── HookRepairer.cpp ├── HookRepairer.h ├── HookRepairer.rc ├── HookRepairer.vcxproj ├── HookRepairer.vcxproj.filters ├── HookRepairer.vcxproj.user ├── HookRepairerDlg.cpp ├── HookRepairerDlg.h ├── Module.cpp ├── Module.h ├── Proc.cpp ├── Proc.h ├── Process.cpp ├── Process.h ├── README.md ├── ReadMe.txt ├── SearchDlg.cpp ├── SearchDlg.h ├── TAB1.cpp ├── TAB1.h ├── TAB2.cpp ├── TAB2.h ├── TAB3.cpp ├── TAB3.h ├── WebPage.cpp ├── WebPage.h ├── cmdlist.cpp ├── disasm.h ├── main.cpp ├── resource.h ├── stdafx.cpp ├── stdafx.h └── targetver.h /CodeSeg.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | CodeSeg::CodeSeg() 4 | { 5 | 6 | } 7 | 8 | CodeSeg::~CodeSeg() 9 | { 10 | 11 | } 12 | 13 | void CodeSeg::Clear() 14 | { 15 | m_Proc.Clear(); 16 | 17 | } 18 | 19 | // ================ 20 | 21 | CodeSegList::CodeSegList() 22 | { 23 | } 24 | 25 | CodeSegList::~CodeSegList() 26 | { 27 | vector().swap(m_vecCodeSegList); 28 | } 29 | 30 | vector::iterator CodeSegList::Begin() 31 | { 32 | return m_vecCodeSegList.begin(); 33 | } 34 | 35 | vector::iterator CodeSegList::End() 36 | { 37 | return m_vecCodeSegList.end(); 38 | } 39 | 40 | void CodeSegList::Copy(CodeSegList src) 41 | { 42 | copy(src.Begin(), src.End(), back_inserter(m_vecCodeSegList)); 43 | } 44 | 45 | void CodeSegList::Clear() 46 | { 47 | for (auto cd : m_vecCodeSegList) 48 | cd.Clear(); 49 | vector().swap(m_vecCodeSegList); 50 | } 51 | 52 | int CodeSegList::Size() 53 | { 54 | return m_vecCodeSegList.size(); 55 | } 56 | 57 | void CodeSegList::Push_Back(CodeSeg m) 58 | { 59 | m_vecCodeSegList.push_back(m); 60 | 61 | } 62 | 63 | void CodeSegList::Pop_Back() 64 | { 65 | m_vecCodeSegList[m_vecCodeSegList.size() - 1].Clear(); 66 | m_vecCodeSegList.pop_back(); 67 | } 68 | 69 | CodeSeg CodeSegList::At(int i) 70 | { 71 | return m_vecCodeSegList[i]; 72 | } 73 | 74 | void CodeSegList::Pop_Front() 75 | { 76 | if (m_vecCodeSegList.size() == 1) { 77 | m_vecCodeSegList.pop_back(); 78 | return; 79 | } // if 80 | 81 | iter_swap(m_vecCodeSegList.begin(), m_vecCodeSegList.end() - 1); 82 | m_vecCodeSegList[m_vecCodeSegList.size()-1].Clear(); 83 | Pop_Back(); 84 | if (m_vecCodeSegList.size() > 1) { 85 | SortByIndex(0); 86 | } // if 87 | } 88 | 89 | void CodeSegList::Sort() 90 | { 91 | if (m_vecCodeSegList.size() <= 1) return; 92 | 93 | for (int i = floor((m_vecCodeSegList.size() - 2) / 2); i >= 0; i--) 94 | SortByIndex(i); 95 | 96 | } 97 | 98 | void CodeSegList::SortByIndex(int root) 99 | { 100 | int lchild = root * 2 + 1; 101 | int rchild = lchild + 1; 102 | int min = root; 103 | int size = m_vecCodeSegList.size(); 104 | int pValue = m_vecCodeSegList[root].m_Proc.m_dwAddr; 105 | int lValue = m_vecCodeSegList[lchild].m_Proc.m_dwAddr; 106 | int rValue = -1; 107 | 108 | 109 | if (rchild < size) rValue = m_vecCodeSegList[rchild].m_Proc.m_dwAddr; 110 | if (lchild < size && (lValue < pValue)) { 111 | min = lchild; 112 | if (rchild < size && (rValue < lValue)) min = rchild; 113 | } // if 114 | else { 115 | if (rchild < size && (rValue < pValue)) min = rchild; 116 | } 117 | 118 | 119 | if (min != root) { 120 | iter_swap(m_vecCodeSegList.begin() + root, m_vecCodeSegList.begin() + min); 121 | if (min * 2 + 1 < size) SortByIndex(min); 122 | } 123 | } 124 | 125 | /* 126 | void CodeSegList::SortByIndex(int root) 127 | { 128 | int lchild = root * 2 + 1; 129 | int rchild = lchild + 1; 130 | int min = root; 131 | int size = m_vecCodeSegList.size(); 132 | int pValue = m_vecCodeSegList[root].m_Module.m_dwAddr; 133 | int lValue = m_vecCodeSegList[lchild].m_Module.m_dwAddr; 134 | int rValue = -1; 135 | 136 | 137 | if (rchild < size) rValue = m_vecCodeSegList[rchild].m_Module.m_dwAddr; 138 | if (lchild < m_vecCodeSegList.size() && (lValue <= pValue)) // ml <= mp 139 | { 140 | if (lValue < pValue) // compare module address ml < mp 141 | { 142 | min = lchild; 143 | if (rchild < size && (rValue <= lValue)) // mr <= ml 144 | { 145 | if (rValue < pValue) // mr < ml 146 | min = rchild; 147 | else // if module address are same mr == ml 148 | { 149 | lValue = m_vecCodeSegList[lchild].m_Proc.m_dwAddr; 150 | rValue = m_vecCodeSegList[rchild].m_Proc.m_dwAddr; 151 | if (rValue < pValue) // compare proc address pr < pl 152 | min = rchild; 153 | } // else 154 | } // if 155 | } // if 156 | else // if module address are same ml == mp 157 | { 158 | pValue = m_vecCodeSegList[root].m_Proc.m_dwAddr; 159 | lValue = m_vecCodeSegList[lchild].m_Proc.m_dwAddr; 160 | if (lValue < pValue) // compare proc address pl < pp 161 | { 162 | min = lchild; 163 | lValue = m_vecCodeSegList[lchild].m_Module.m_dwAddr; // resume module address 164 | if (rchild < size && (rValue <= lValue)) // compare module address mr <= ml 165 | { 166 | if (rValue < lValue) // mr < ml 167 | min = rchild; 168 | else // if module address are same mr == ml 169 | { 170 | lValue = m_vecCodeSegList[lchild].m_Proc.m_dwAddr; 171 | rValue = m_vecCodeSegList[rchild].m_Proc.m_dwAddr; 172 | if (rValue < lValue) // compare proc address pr < pl 173 | min = rchild; 174 | } // else 175 | } // if 176 | } // if 177 | 178 | } 179 | } // if 180 | else // ml > mp 181 | { 182 | if (rchild < size && (rValue <= pValue)) // mr <= mp 183 | { 184 | if (rValue < pValue) // mr < mp 185 | min = rchild; 186 | else // if module address are same mr == mp 187 | { 188 | pValue = m_vecCodeSegList[root].m_Proc.m_dwAddr; 189 | rValue = m_vecCodeSegList[rchild].m_Proc.m_dwAddr; 190 | if (rValue < pValue) // compare proc address pr < pp 191 | min = rchild; 192 | } // else 193 | } // if 194 | } 195 | 196 | 197 | if (min != root) { 198 | iter_swap(m_vecCodeSegList.begin() + root, m_vecCodeSegList.begin() + min); 199 | if (min * 2 + 1 < size) SortByIndex(min); 200 | } 201 | } 202 | 203 | */ -------------------------------------------------------------------------------- /CodeSeg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | using namespace std; 4 | class CodeSeg 5 | { 6 | public: 7 | Module m_Module; 8 | Proc m_Proc; 9 | DWORD m_dwCodeAddr; 10 | int m_iLength; 11 | string m_strCode; 12 | string m_strOriginCode; 13 | CodeSeg(); 14 | ~CodeSeg(); 15 | void Clear(); 16 | private: 17 | }; 18 | 19 | class CodeSegList 20 | { 21 | public: 22 | CodeSegList(); 23 | ~CodeSegList(); 24 | void Clear(); 25 | int Size(); 26 | void Push_Back(CodeSeg cs); 27 | void Pop_Back(); 28 | void Sort(); 29 | void Pop_Front(); 30 | void Copy(CodeSegList src); 31 | vector::iterator Begin(); 32 | vector::iterator End(); 33 | CodeSeg At(int i); 34 | private: 35 | void SortByIndex(int root); 36 | vector m_vecCodeSegList; 37 | 38 | }; -------------------------------------------------------------------------------- /DetourInfo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/DetourInfo.cpp -------------------------------------------------------------------------------- /DetourInfo.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/DetourInfo.h -------------------------------------------------------------------------------- /DumpInfoDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/DumpInfoDlg.cpp -------------------------------------------------------------------------------- /DumpInfoDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/DumpInfoDlg.h -------------------------------------------------------------------------------- /EasySize.h: -------------------------------------------------------------------------------- 1 | /*===================================================*\ 2 | | | 3 | | EASY-SIZE Macros | 4 | | | 5 | | Copyright (c) 2001 - Marc Richarme | 6 | | devix@devix.cjb.net | 7 | | http://devix.cjb.net | 8 | | | 9 | | License: | 10 | | | 11 | | You may use this code in any commersial or non- | 12 | | commersial application, and you may redistribute | 13 | | this file (and even modify it if you wish) as | 14 | | long as you keep this notice untouched in any | 15 | | version you redistribute. | 16 | | | 17 | | Usage: | 18 | | | 19 | | - Insert 'DECLARE_EASYSIZE' somewhere in your | 20 | | class declaration | 21 | | - Insert an easysize map in the beginning of your | 22 | | class implementation (see documentation) and | 23 | | outside of any function. | 24 | | - Insert 'INIT_EASYSIZE;' in your | 25 | | OnInitDialog handler. | 26 | | - Insert 'UPDATE_EASYSIZE' in your OnSize handler | 27 | | - Optional: Insert 'EASYSIZE_MINSIZE(mx,my);' in | 28 | | your OnSizing handler if you want to specify | 29 | | a minimum size for your dialog | 30 | | | 31 | | Check http://devix.cjb.net for the | 32 | | docs and new versions | 33 | | | 34 | \*===================================================*/ 35 | 36 | 37 | #ifndef __EASYSIZE_H_ 38 | #define __EASYSIZE_H_ 39 | #define ES_BORDER 0xffffffff 40 | #define ES_KEEPSIZE 0xfffffffe 41 | #define ES_HCENTER 0x00000001 42 | #define ES_VCENTER 0x00000002 43 | #define DECLARE_EASYSIZE \ 44 | void __ES__RepositionControls(BOOL bInit);\ 45 | void __ES__CalcBottomRight(CWnd *pThis, BOOL bBottom, int &bottomright, int &topleft, UINT id, UINT br, int es_br, CRect &rect, int clientbottomright); 46 | #define INIT_EASYSIZE __ES__RepositionControls(TRUE); __ES__RepositionControls(FALSE) 47 | #define UPDATE_EASYSIZE if(GetWindow(GW_CHILD)!=NULL) __ES__RepositionControls(FALSE) 48 | #define EASYSIZE_MINSIZE(mx,my,s,r) if(r->right-r->left < mx) { if((s == WMSZ_BOTTOMLEFT)||(s == WMSZ_LEFT)||(s == WMSZ_TOPLEFT)) r->left = r->right-mx; else r->right = r->left+mx; } if(r->bottom-r->top < my) { if((s == WMSZ_TOP)||(s == WMSZ_TOPLEFT)||(s == WMSZ_TOPRIGHT)) r->top = r->bottom-my; else r->bottom = r->top+my; } 49 | #define BEGIN_EASYSIZE_MAP(class) \ 50 | void class::__ES__CalcBottomRight(CWnd *pThis, BOOL bBottom, int &bottomright, int &topleft, UINT id, UINT br, int es_br, CRect &rect, int clientbottomright) {\ 51 | if(br==ES_BORDER) bottomright = clientbottomright-es_br;\ 52 | else if(br==ES_KEEPSIZE) bottomright = topleft+es_br;\ 53 | else { CRect rect2;\ 54 | pThis->GetDlgItem(br)->GetWindowRect(rect2); pThis->ScreenToClient(rect2);\ 55 | bottomright = (bBottom?rect2.top:rect2.left) - es_br;}}\ 56 | void class::__ES__RepositionControls(BOOL bInit) { CRect rect,rect2,client; GetClientRect(client); 57 | #define END_EASYSIZE_MAP Invalidate(); UpdateWindow(); } 58 | #define EASYSIZE(id,l,t,r,b,o) \ 59 | static int id##_es_l, id##_es_t, id##_es_r, id##_es_b;\ 60 | if(bInit) {\ 61 | GetDlgItem(id)->GetWindowRect(rect); ScreenToClient(rect);\ 62 | if(o & ES_HCENTER) id##_es_l = rect.Width()/2; else {\ 63 | if(l==ES_BORDER) id##_es_l = rect.left; else if(l==ES_KEEPSIZE) id##_es_l = rect.Width(); else {\ 64 | GetDlgItem(l)->GetWindowRect(rect2); ScreenToClient(rect2);\ 65 | id##_es_l = rect.left-rect2.right;}}\ 66 | if(o & ES_VCENTER) id##_es_t = rect.Height()/2; else {\ 67 | if(t==ES_BORDER) id##_es_t = rect.top; else if(t==ES_KEEPSIZE) id##_es_t = rect.Height(); else {\ 68 | GetDlgItem(t)->GetWindowRect(rect2); ScreenToClient(rect2);\ 69 | id##_es_t = rect.top-rect2.bottom;}}\ 70 | if(o & ES_HCENTER) id##_es_r = rect.Width(); else { if(r==ES_BORDER) id##_es_r = client.right-rect.right; else if(r==ES_KEEPSIZE) id##_es_r = rect.Width(); else {\ 71 | GetDlgItem(r)->GetWindowRect(rect2); ScreenToClient(rect2);\ 72 | id##_es_r = rect2.left-rect.right;}}\ 73 | if(o & ES_VCENTER) id##_es_b = rect.Height(); else { if(b==ES_BORDER) id##_es_b = client.bottom-rect.bottom; else if(b==ES_KEEPSIZE) id##_es_b = rect.Height(); else {\ 74 | GetDlgItem(b)->GetWindowRect(rect2); ScreenToClient(rect2);\ 75 | id##_es_b = rect2.top-rect.bottom;}}\ 76 | } else {\ 77 | int left,top,right,bottom; BOOL bR = FALSE,bB = FALSE;\ 78 | if(o & ES_HCENTER) { int _a,_b;\ 79 | if(l==ES_BORDER) _a = client.left; else { GetDlgItem(l)->GetWindowRect(rect2); ScreenToClient(rect2); _a = rect2.right; }\ 80 | if(r==ES_BORDER) _b = client.right; else { GetDlgItem(r)->GetWindowRect(rect2); ScreenToClient(rect2); _b = rect2.left; }\ 81 | left = _a+((_b-_a)/2-id##_es_l); right = left + id##_es_r;} else {\ 82 | if(l==ES_BORDER) left = id##_es_l;\ 83 | else if(l==ES_KEEPSIZE) { __ES__CalcBottomRight(this,FALSE,right,left,id,r,id##_es_r,rect,client.right); left = right-id##_es_l;\ 84 | } else { GetDlgItem(l)->GetWindowRect(rect2); ScreenToClient(rect2); left = rect2.right + id##_es_l; }\ 85 | if(l != ES_KEEPSIZE) __ES__CalcBottomRight(this,FALSE,right,left,id,r,id##_es_r,rect,client.right);}\ 86 | if(o & ES_VCENTER) { int _a,_b;\ 87 | if(t==ES_BORDER) _a = client.top; else { GetDlgItem(t)->GetWindowRect(rect2); ScreenToClient(rect2); _a = rect2.bottom; }\ 88 | if(b==ES_BORDER) _b = client.bottom; else { GetDlgItem(b)->GetWindowRect(rect2); ScreenToClient(rect2); _b = rect2.top; }\ 89 | top = _a+((_b-_a)/2-id##_es_t); bottom = top + id##_es_b;} else {\ 90 | if(t==ES_BORDER) top = id##_es_t;\ 91 | else if(t==ES_KEEPSIZE) { __ES__CalcBottomRight(this,TRUE,bottom,top,id,b,id##_es_b,rect,client.bottom); top = bottom-id##_es_t;\ 92 | } else { GetDlgItem(t)->GetWindowRect(rect2); ScreenToClient(rect2); top = rect2.bottom + id##_es_t; }\ 93 | if(t != ES_KEEPSIZE) __ES__CalcBottomRight(this,TRUE,bottom,top,id,b,id##_es_b,rect,client.bottom);}\ 94 | GetDlgItem(id)->MoveWindow(left,top,right-left,bottom-top,FALSE);\ 95 | } 96 | #endif //__EASYSIZE_H_ -------------------------------------------------------------------------------- /HookInfoDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookInfoDlg.cpp -------------------------------------------------------------------------------- /HookInfoDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookInfoDlg.h -------------------------------------------------------------------------------- /HookRepairer.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookRepairer.aps -------------------------------------------------------------------------------- /HookRepairer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookRepairer.cpp -------------------------------------------------------------------------------- /HookRepairer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookRepairer.h -------------------------------------------------------------------------------- /HookRepairer.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookRepairer.rc -------------------------------------------------------------------------------- /HookRepairer.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {DC78F08E-2B6B-4844-8A89-090F355B1ACA} 23 | HookRepairer 24 | 8.1 25 | MFCProj 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | MultiByte 33 | Dynamic 34 | 35 | 36 | Application 37 | false 38 | v140_xp 39 | true 40 | MultiByte 41 | Dynamic 42 | 43 | 44 | Application 45 | true 46 | v140 47 | Unicode 48 | Dynamic 49 | 50 | 51 | Application 52 | false 53 | v140 54 | true 55 | MultiByte 56 | Dynamic 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | true 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | false 87 | 88 | 89 | 90 | Use 91 | Level3 92 | Disabled 93 | WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) 94 | true 95 | 96 | 97 | Windows 98 | 99 | 100 | false 101 | true 102 | _DEBUG;%(PreprocessorDefinitions) 103 | 104 | 105 | 0x0404 106 | _DEBUG;%(PreprocessorDefinitions) 107 | $(IntDir);%(AdditionalIncludeDirectories) 108 | 109 | 110 | 111 | 112 | Use 113 | Level3 114 | Disabled 115 | _WINDOWS;_DEBUG;%(PreprocessorDefinitions) 116 | true 117 | 118 | 119 | Windows 120 | 121 | 122 | false 123 | true 124 | _DEBUG;%(PreprocessorDefinitions) 125 | 126 | 127 | 0x0404 128 | _DEBUG;%(PreprocessorDefinitions) 129 | $(IntDir);%(AdditionalIncludeDirectories) 130 | 131 | 132 | 133 | 134 | Level3 135 | NotUsing 136 | MaxSpeed 137 | true 138 | true 139 | WIN32;_WINDOWS;NDEBUG;_ATL_ALLOW_CHAR_UNSIGNED;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) 140 | true 141 | stdafx.h 142 | 143 | 144 | Windows 145 | true 146 | true 147 | Dbghelp.lib;Psapi.lib;%(AdditionalDependencies) 148 | 149 | 150 | false 151 | true 152 | NDEBUG;%(PreprocessorDefinitions) 153 | 154 | 155 | 0x0404 156 | NDEBUG;%(PreprocessorDefinitions) 157 | $(IntDir);%(AdditionalIncludeDirectories) 158 | 159 | 160 | 161 | 162 | Level3 163 | NotUsing 164 | MaxSpeed 165 | true 166 | true 167 | _WINDOWS;NDEBUG;_ATL_ALLOW_CHAR_UNSIGNED;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) 168 | true 169 | 170 | 171 | Windows 172 | true 173 | true 174 | Dbghelp.lib 175 | 176 | 177 | false 178 | true 179 | NDEBUG;%(PreprocessorDefinitions) 180 | 181 | 182 | 0x0404 183 | NDEBUG;%(PreprocessorDefinitions) 184 | $(IntDir);%(AdditionalIncludeDirectories) 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | Create 224 | Create 225 | Create 226 | Create 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /HookRepairer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 標頭檔 23 | 24 | 25 | 標頭檔 26 | 27 | 28 | 標頭檔 29 | 30 | 31 | 標頭檔 32 | 33 | 34 | 標頭檔 35 | 36 | 37 | 標頭檔 38 | 39 | 40 | 標頭檔 41 | 42 | 43 | 標頭檔 44 | 45 | 46 | 標頭檔 47 | 48 | 49 | 標頭檔 50 | 51 | 52 | 標頭檔 53 | 54 | 55 | 標頭檔 56 | 57 | 58 | 標頭檔 59 | 60 | 61 | 標頭檔 62 | 63 | 64 | 標頭檔 65 | 66 | 67 | 標頭檔 68 | 69 | 70 | 標頭檔 71 | 72 | 73 | 74 | 75 | 原始程式檔 76 | 77 | 78 | 原始程式檔 79 | 80 | 81 | 原始程式檔 82 | 83 | 84 | 原始程式檔 85 | 86 | 87 | 原始程式檔 88 | 89 | 90 | 原始程式檔 91 | 92 | 93 | 原始程式檔 94 | 95 | 96 | 原始程式檔 97 | 98 | 99 | 原始程式檔 100 | 101 | 102 | 原始程式檔 103 | 104 | 105 | 原始程式檔 106 | 107 | 108 | 原始程式檔 109 | 110 | 111 | 原始程式檔 112 | 113 | 114 | 原始程式檔 115 | 116 | 117 | 原始程式檔 118 | 119 | 120 | 原始程式檔 121 | 122 | 123 | 124 | 125 | 資源檔 126 | 127 | 128 | 129 | 130 | 資源檔 131 | 132 | 133 | 134 | 135 | 資源檔 136 | 137 | 138 | 資源檔 139 | 140 | 141 | -------------------------------------------------------------------------------- /HookRepairer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /HookRepairerDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookRepairerDlg.cpp -------------------------------------------------------------------------------- /HookRepairerDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/HookRepairerDlg.h -------------------------------------------------------------------------------- /Module.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | 4 | Module::Module() 5 | { 6 | } 7 | 8 | Module::Module(string n, DWORD a, string p) 9 | { 10 | m_strName = n; 11 | m_dwAddr = a; 12 | m_strPath = p; 13 | } 14 | 15 | Module::~Module() 16 | { 17 | 18 | } 19 | 20 | /*bool Module::GetModuleProcs(CodeSegList* prList) 21 | { 22 | bool b_NeedRemoveDLL = false; 23 | HMODULE hModule = GetModuleHandle(m_strName.c_str()); 24 | if (hModule == NULL) 25 | { 26 | b_NeedRemoveDLL = true; 27 | hModule = LoadLibraryA(m_strName.c_str()); 28 | } // if 29 | 30 | if (hModule == NULL) return false; 31 | uint8_t* dwModuleBase = (uint8_t*)hModule; 32 | IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)dwModuleBase; 33 | if (pDosHeader == NULL) return false; 34 | IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(dwModuleBase + pDosHeader->e_lfanew); 35 | 36 | if (pNTHeaders == NULL) return false; 37 | // 加載器將文件裝入內存並將導入表(導出表)登記的動態鏈接庫(一般是DLL格式)文件一併裝入地址空間, //数据的起始RVA 38 | IMAGE_EXPORT_DIRECTORY* pExpHeader = (IMAGE_EXPORT_DIRECTORY*)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + dwModuleBase); 39 | if (pExpHeader == NULL) return false; 40 | 41 | size_t szModuleSize = pNTHeaders->OptionalHeader.SizeOfImage; 42 | DWORD* pName = (DWORD*)(pExpHeader->AddressOfNames + dwModuleBase); 43 | DWORD* pAddress = (DWORD*)(pExpHeader->AddressOfFunctions + dwModuleBase); // 起始function Address 44 | WORD* pOrdinals = (WORD*)(pExpHeader->AddressOfNameOrdinals + dwModuleBase); // 取得指向輸出函數序號的RVA 45 | 46 | for (int i = 0; i < pExpHeader->NumberOfNames; i++) 47 | { 48 | //WORD wAddressIndex = pOrdinals[i]; // 取得函數序號的內容 49 | const char* pszFunctionName = (const char *)(pName[i] + dwModuleBase); // function name 50 | //MessageBox(NULL, pszFunctionName, "", MB_OK); 51 | CodeSeg mTmp; 52 | mTmp.m_Module.m_strName = m_strName; 53 | mTmp.m_Module.m_dwAddr = (DWORD)dwModuleBase; 54 | mTmp.m_Proc.m_dwAddr = (DWORD)dwModuleBase + pAddress[pOrdinals[i]]; 55 | mTmp.m_Proc.m_strName = pszFunctionName; 56 | if ( i < pExpHeader->NumberOfNames - 1) 57 | mTmp.m_Proc.m_dwSize = (DWORD)dwModuleBase + (pAddress[pOrdinals[i+1]] - pAddress[pOrdinals[i]]); 58 | else 59 | mTmp.m_Proc.m_dwSize = (DWORD)dwModuleBase + (pAddress[pOrdinals[i + 1]] - pAddress[pOrdinals[i]]); 60 | prList->Push_Back(mTmp); 61 | 62 | } // for 63 | 64 | prList->Sort(); 65 | CodeSeg mEnd; 66 | mEnd.m_Proc.m_dwAddr = (DWORD)(dwModuleBase + szModuleSize); 67 | CodeSegList tmpList; 68 | tmpList.Copy(*prList); 69 | for (int i = 0; i < pExpHeader->NumberOfNames; i++) 70 | { 71 | CodeSeg* mCur = &tmpList.At(0); 72 | CodeSeg* mNext = &mEnd; 73 | tmpList.Pop_Front(); 74 | if (tmpList.Size() > 0) 75 | mNext = &tmpList.At(0); 76 | mCur->m_Proc.m_dwSize = mNext->m_Proc.m_dwAddr - mCur->m_Proc.m_dwAddr; 77 | } 78 | 79 | if (b_NeedRemoveDLL) 80 | FreeLibrary(hModule); 81 | tmpList.Clear(); 82 | }*/ 83 | 84 | 85 | // =========================================================================================== 86 | ModuleList::ModuleList() 87 | { 88 | } 89 | 90 | ModuleList::~ModuleList() 91 | { 92 | vector().swap(m_vecModuleList); 93 | } 94 | 95 | vector::iterator ModuleList::Begin() 96 | { 97 | return m_vecModuleList.begin(); 98 | } 99 | 100 | vector::iterator ModuleList::End() 101 | { 102 | return m_vecModuleList.end(); 103 | } 104 | 105 | void ModuleList::Copy(ModuleList src) 106 | { 107 | copy(src.Begin(), src.End(), back_inserter(m_vecModuleList)); 108 | } 109 | 110 | void ModuleList::Clear() 111 | { 112 | vector().swap(m_vecModuleList); 113 | } 114 | 115 | int ModuleList::Size() 116 | { 117 | return m_vecModuleList.size(); 118 | } 119 | 120 | void ModuleList::Push_Back(Module m) 121 | { 122 | m_vecModuleList.push_back(m); 123 | 124 | } 125 | 126 | void ModuleList::Pop_Back() 127 | { 128 | //m_vecModuleList[m_vecModuleList.size() - 1].Clear(); 129 | m_vecModuleList.pop_back(); 130 | } 131 | 132 | Module ModuleList::At(int i) 133 | { 134 | return m_vecModuleList[i]; 135 | } 136 | 137 | void ModuleList::Pop_Front() 138 | { 139 | if (m_vecModuleList.size() == 1) { 140 | m_vecModuleList.pop_back(); 141 | return; 142 | } // if 143 | 144 | iter_swap(m_vecModuleList.begin(), m_vecModuleList.end() - 1); 145 | Pop_Back(); 146 | if (m_vecModuleList.size() > 1) { 147 | SortByIndex(0); 148 | } // if 149 | } 150 | 151 | void ModuleList::Sort() 152 | { 153 | if (m_vecModuleList.size() <= 1) return; 154 | 155 | for (int i = floor((m_vecModuleList.size() - 2) / 2); i >= 0; i--) 156 | SortByIndex(i); 157 | 158 | } 159 | 160 | void ModuleList::SortByIndex(int root) 161 | { 162 | int lchild = root * 2 + 1; 163 | int rchild = lchild + 1; 164 | int min = root; 165 | int size = m_vecModuleList.size(); 166 | int pValue = m_vecModuleList[root].m_dwAddr; 167 | int lValue = m_vecModuleList[lchild].m_dwAddr; 168 | int rValue = -1; 169 | 170 | 171 | if (rchild < size) rValue = m_vecModuleList[rchild].m_dwAddr; 172 | if (lchild < m_vecModuleList.size() && (lValue < pValue)) { 173 | min = lchild; 174 | if (rchild < size && (rValue < lValue)) min = rchild; 175 | } // if 176 | else { 177 | if (rchild < size && (rValue < pValue)) min = rchild; 178 | } 179 | 180 | 181 | if (min != root) { 182 | iter_swap(m_vecModuleList.begin() + root, m_vecModuleList.begin() + min); 183 | if (min * 2 + 1 < size) SortByIndex(min); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /Module.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | using namespace std; 4 | class Module 5 | { 6 | public: 7 | Module(); 8 | Module( string n, DWORD a, string p); 9 | ~Module(); 10 | string m_strName; 11 | DWORD m_dwAddr; 12 | string m_strPath; 13 | //bool GetModuleProcs(CodeSegList* prList); 14 | private: 15 | }; 16 | 17 | class ModuleList 18 | { 19 | public: 20 | ModuleList(); 21 | ~ModuleList(); 22 | vector::iterator Begin(); 23 | vector::iterator End(); 24 | void Copy(ModuleList src); 25 | void Clear(); 26 | int Size(); 27 | void Push_Back(Module m); 28 | void Pop_Back(); 29 | void Sort(); 30 | void Pop_Front(); 31 | Module At(int i); 32 | private: 33 | void SortByIndex( int root ); 34 | vector m_vecModuleList; 35 | }; 36 | -------------------------------------------------------------------------------- /Proc.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include "disasm.h" 4 | Proc::Proc() 5 | { 6 | m_dwSize = m_dwAddr = 0; 7 | m_btCode = NULL; 8 | } 9 | 10 | Proc::~Proc() 11 | { 12 | 13 | } 14 | 15 | void Proc::Clear() 16 | { 17 | if (m_btCode != NULL) 18 | { 19 | delete[] m_btCode; 20 | m_btCode = NULL; 21 | } // if 22 | 23 | } 24 | 25 | bool Proc::FindDetourAddress(string strDLL, vector* vecStrResult) 26 | { 27 | HMODULE hDLL = GetModuleHandle(strDLL.c_str()); 28 | bool b_NeedFreeLib = false; 29 | if (hDLL == NULL) { 30 | LoadLibraryA(strDLL.c_str()); 31 | b_NeedFreeLib = true; 32 | hDLL = GetModuleHandle(strDLL.c_str()); 33 | if (hDLL == NULL) 34 | { 35 | MessageBox(NULL, strDLL.c_str(), "Can't find this module.", MB_OK); 36 | return false; 37 | } // if 38 | } // if 39 | 40 | Preparedisasm(); 41 | SIZE_T lpRead; 42 | uchar* btOriginCode = (uchar*)m_dwAddr; 43 | int i_recordCounts = 0, i_zeroCount = 0; 44 | ulong cmdLength; 45 | t_disasm da_Origin; 46 | t_config config; 47 | config.lowercase = true; 48 | //config.hiliteoperands = true; 49 | CString oldCode, oldBytes; 50 | int oldLength = 0; 51 | for (int i = 0; i < m_dwSize; i += cmdLength) 52 | { 53 | cmdLength = Disasm((uchar*)(btOriginCode + i), m_dwSize - i, (DWORD)(btOriginCode + i), &da_Origin, DA_TEXT | DA_DUMP, &config, NULL); 54 | if (cmdLength == 0) 55 | { 56 | MessageBox(NULL, "Error - Nothing found.", "SORRY", MB_OK); 57 | break; 58 | } // if 59 | 60 | /*if (da_Origin.errors > 0 || da_Origin.warnings > 0) 61 | { 62 | continue; 63 | } // if*/ 64 | 65 | if (cmdLength == 5 || cmdLength == 6) 66 | { 67 | i_recordCounts++; 68 | HookInfo hi; 69 | hi.m_strProcName = m_strName.c_str(); 70 | hi.m_strAddr.Format( "0x%x", (DWORD)(btOriginCode + i)); 71 | hi.m_strRetAddr.Format( "0x%x", (DWORD)(btOriginCode + i) + cmdLength); 72 | hi.m_strDLength.Format( "%d", cmdLength); 73 | hi.m_strBytes = da_Origin.dump; 74 | hi.m_strCode = da_Origin.result; 75 | vecStrResult->push_back(hi); 76 | //MessageBoxHex(NULL, (DWORD)(btOriginCode + i), cmdLength); 77 | //break; 78 | } // if 79 | else if (oldLength + cmdLength == 5 || oldLength + cmdLength == 6) // sutibale detour address 80 | { // 7740A40d kernal32 81 | i_recordCounts++; 82 | HookInfo hi; 83 | hi.m_strProcName = m_strName.c_str(); 84 | hi.m_strAddr.Format("0x%x", (DWORD)(btOriginCode + i)); 85 | hi.m_strRetAddr.Format("0x%x", (DWORD)(btOriginCode + i) + cmdLength); 86 | hi.m_strDLength.Format("%d", cmdLength + oldLength); 87 | hi.m_strBytes = (oldBytes + "\r\n"); 88 | hi.m_strBytes += da_Origin.dump; 89 | hi.m_strCode = (oldCode + "\r\n"); 90 | hi.m_strCode += da_Origin.result; 91 | vecStrResult->push_back(hi); 92 | //MessageBoxHex(NULL, (DWORD)(btOriginCode + i - oldLength), oldLength + cmdLength); 93 | //break; 94 | } // else if 95 | 96 | if ((*(btOriginCode + i) == 0x0 && i_zeroCount++ >= 10) || 97 | *(btOriginCode + i) == 0xcc) break; // *(btOriginCode + i) == 0xc2 || *(btOriginCode + i) == 0xc3 || 98 | oldLength = cmdLength; 99 | oldCode = da_Origin.result; 100 | oldBytes = da_Origin.dump; 101 | 102 | } // for 103 | 104 | Finishdisasm(); 105 | if(b_NeedFreeLib) FreeLibrary(hDLL); 106 | if (i_recordCounts == 0) MessageBox(NULL, "Nothing found.", "SORRY", MB_OK); 107 | return true; 108 | } 109 | bool Proc::DumpFunction(string strDLL, vector* vecDump) 110 | { 111 | HMODULE hDLL = GetModuleHandle(strDLL.c_str()); 112 | bool b_NeedFreeLib = false; 113 | if (hDLL == NULL) { 114 | LoadLibraryA(strDLL.c_str()); 115 | b_NeedFreeLib = true; 116 | hDLL = GetModuleHandle(strDLL.c_str()); 117 | if (hDLL == NULL) 118 | { 119 | MessageBox(NULL, strDLL.c_str(), "Can't find this module.", MB_OK); 120 | return false; 121 | } // if 122 | } // if 123 | 124 | Preparedisasm(); 125 | SIZE_T lpRead; 126 | uchar* btOriginCode = (uchar*)m_dwAddr; 127 | //MessageBoxHex(NULL, m_dwAddr, 0); 128 | int i_zeroCount = 0; 129 | ulong cmdLength; 130 | t_disasm da_Origin; 131 | t_config config; 132 | config.lowercase = true; 133 | for (int i = 0; i < m_dwSize; i += cmdLength) 134 | { 135 | cmdLength = Disasm((uchar*)(btOriginCode + i), m_dwSize - i, (DWORD)(btOriginCode + i), &da_Origin, DA_TEXT | DA_DUMP, &config, NULL); 136 | if (cmdLength == 0) 137 | { 138 | MessageBox(NULL, "Dump Error.", "ERROR", MB_OK); 139 | break; 140 | } // if 141 | 142 | /*if (da_Origin.errors > 0 || da_Origin.warnings > 0) 143 | { 144 | continue; 145 | } // if*/ 146 | 147 | HookInfo hi; 148 | hi.m_strProcName = m_strName.c_str(); 149 | hi.m_strAddr.Format("0x%x", (DWORD)(btOriginCode + i)); 150 | hi.m_strDLength.Format("%d", cmdLength); 151 | hi.m_strBytes.Format( "%-32s", da_Origin.dump); 152 | hi.m_strCode.Format( "%-50s", da_Origin.result); 153 | vecDump->push_back(hi); 154 | 155 | if ((*(btOriginCode + i) == 0x0 && i_zeroCount++ >= 10) || 156 | *(btOriginCode + i) == 0xcc) break; 157 | } // for 158 | 159 | Finishdisasm(); 160 | if (b_NeedFreeLib) FreeLibrary(hDLL); 161 | return true; 162 | } 163 | // ================================================================== 164 | ProcList::ProcList() 165 | { 166 | } 167 | 168 | ProcList::~ProcList() 169 | { 170 | vector().swap(m_vecProcList); 171 | } 172 | 173 | vector::iterator ProcList::Begin() 174 | { 175 | return m_vecProcList.begin(); 176 | } 177 | 178 | vector::iterator ProcList::End() 179 | { 180 | return m_vecProcList.end(); 181 | 182 | } 183 | 184 | void ProcList::Copy(ProcList src) 185 | { 186 | copy(src.Begin(), src.End(), back_inserter(m_vecProcList)); 187 | } 188 | void ProcList::Clear() 189 | { 190 | for (auto pc : m_vecProcList) 191 | pc.Clear(); 192 | vector().swap(m_vecProcList); 193 | } 194 | 195 | int ProcList::Size() 196 | { 197 | return m_vecProcList.size(); 198 | } 199 | 200 | void ProcList::Push_Back(Proc m) 201 | { 202 | m_vecProcList.push_back(m); 203 | 204 | } 205 | 206 | void ProcList::Pop_Back() 207 | { 208 | m_vecProcList[m_vecProcList.size() - 1].Clear(); 209 | m_vecProcList.pop_back(); 210 | } 211 | 212 | Proc ProcList::At(int i) 213 | { 214 | return m_vecProcList[i]; 215 | } 216 | 217 | void ProcList::Pop_Front() 218 | { 219 | if (m_vecProcList.size() == 1) { 220 | m_vecProcList.pop_back(); 221 | return; 222 | } // if 223 | 224 | iter_swap(m_vecProcList.begin(), m_vecProcList.end() - 1); 225 | Pop_Back(); 226 | if (m_vecProcList.size() > 1) { 227 | SortByIndex(0); 228 | } // if 229 | } 230 | 231 | void ProcList::Sort() 232 | { 233 | if (m_vecProcList.size() <= 1) return; 234 | 235 | for (int i = floor((m_vecProcList.size() - 2) / 2); i >= 0; i--) 236 | SortByIndex(i); 237 | 238 | } 239 | 240 | void ProcList::SortByIndex(int root) 241 | { 242 | int lchild = root * 2 + 1; 243 | int rchild = lchild + 1; 244 | int min = root; 245 | int size = m_vecProcList.size(); 246 | int pValue = m_vecProcList[root].m_dwAddr; 247 | int lValue = m_vecProcList[lchild].m_dwAddr; 248 | int rValue = -1; 249 | 250 | 251 | if (rchild < size) rValue = m_vecProcList[rchild].m_dwAddr; 252 | if (lchild < m_vecProcList.size() && (lValue < pValue)) { 253 | min = lchild; 254 | if (rchild < size && (rValue < lValue)) min = rchild; 255 | } // if 256 | else { 257 | if (rchild < size && (rValue < pValue)) min = rchild; 258 | } 259 | 260 | 261 | if (min != root) { 262 | iter_swap(m_vecProcList.begin() + root, m_vecProcList.begin() + min); 263 | if (min * 2 + 1 < size) SortByIndex(min); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /Proc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | using namespace std; 4 | 5 | //typedef vector VecCString; 6 | struct HookInfo 7 | { 8 | CString m_strProcName; 9 | CString m_strAddr; 10 | CString m_strRetAddr; 11 | CString m_strDLength; 12 | CString m_strBytes; 13 | CString m_strCode; 14 | }; 15 | 16 | class Proc 17 | { 18 | public: 19 | string m_strName; 20 | DWORD m_dwAddr; 21 | DWORD m_dwSize; 22 | byte* m_btCode; 23 | Proc(); 24 | ~Proc(); 25 | void Clear(); 26 | bool FindDetourAddress(string strDLL, vector* vecStrResult); 27 | bool DumpFunction(string strDLL, vector* vecDump); 28 | //bool FindDetourAddress(HANDLE hProcess); // find out the address that we can use it to do detour hook 29 | private: 30 | 31 | }; 32 | 33 | class ProcList 34 | { 35 | public: 36 | ProcList(); 37 | ~ProcList(); 38 | vector::iterator Begin(); 39 | vector::iterator End(); 40 | void Copy(ProcList src); 41 | void Clear(); 42 | int Size(); 43 | void Push_Back(Proc c); 44 | void Pop_Back(); 45 | void Sort(); 46 | void Pop_Front(); 47 | Proc At(int i); 48 | private: 49 | void SortByIndex(int root); 50 | vector m_vecProcList; 51 | }; 52 | -------------------------------------------------------------------------------- /Process.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | using namespace std; 3 | #include // uint8_t ... 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "disasm.h" 11 | 12 | static ProcList procList; 13 | Process::Process() 14 | { 15 | } 16 | 17 | Process::Process( DWORD dw, char* str, HANDLE handle ) 18 | { 19 | m_dwPid = dw; 20 | m_strName = str; 21 | m_hProcess = handle; 22 | } 23 | 24 | Process::~Process() 25 | { 26 | m_vecModule.Clear(); 27 | m_vecDifferentCode.Clear(); 28 | OpenProcessHandle(); 29 | } 30 | 31 | void Process::DeleteDifferentCodeList() 32 | { 33 | /*for ( int i = m_vecDifferentCode.size()-1; i >=0 ; i-- ) 34 | { 35 | CodeSeg* cs = &m_vecDifferentCode[i]; 36 | //m_vecDifferentCode.erase(m_vecDifferentCode.begin()+i, m_vecDifferentCode.begin()+(i+1)); 37 | if (cs != NULL) 38 | { 39 | delete cs; 40 | cs = NULL; 41 | } // if 42 | } // for 43 | 44 | for (auto cd : m_vecDifferentCode) 45 | { 46 | cd.Clear(); 47 | } 48 | 49 | vector().swap(m_vecDifferentCode);*/ 50 | } 51 | 52 | bool Process::Terminate() { 53 | if (m_dwPid != 0) { 54 | OpenProcessHandle(); 55 | TerminateProcess(m_hProcess, 1); 56 | CloseProcessHandle(); 57 | Clear(); 58 | return true; 59 | } 60 | 61 | MessageBox( NULL, "Terminate process failed.", "ERROR", MB_OK); 62 | return false; 63 | } 64 | 65 | void Process::Copy(Process* src) 66 | { 67 | m_dwPid = src->m_dwPid; 68 | m_hIcon = src->m_hIcon; 69 | m_hProcess = src->m_hProcess; 70 | m_hWnd = src->m_hWnd; 71 | m_strName = src->m_strName; 72 | m_strPath = src->m_strPath; 73 | m_vecDifferentCode.Copy(src->m_vecDifferentCode); 74 | m_vecModule.Copy(src->m_vecModule); 75 | //copy(src->m_vecDifferentCode.begin(), src->m_vecDifferentCode.End(), back_inserter(m_vecDifferentCode)); 76 | //copy(src->m_vecModule.Begin(), src->m_vecModule.End(), back_inserter(m_vecModule)); 77 | } 78 | 79 | void Process::Clear() 80 | { 81 | //DeleteDifferentCodeList(); 82 | //vector().swap(m_vecDifferentCode); 83 | m_vecDifferentCode.Clear(); 84 | m_vecModule.Clear(); 85 | CloseProcessHandle(); 86 | } 87 | 88 | //typedef DWORD (*MyGetModuleFileNameEX)( HANDLE hProcess, HMODULE hModule,LPSTR lpFilename, DWORD nSize); 89 | //typedef BOOL (*MyEnumProcessModulesEX)( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded); 90 | bool Process::GetAllModule() 91 | { 92 | Clear(); 93 | OpenProcessHandle(); 94 | DWORD dwNeed = 0; 95 | HMODULE* hAllModule = new HMODULE[1000]; 96 | //MyEnumProcessModulesEX EnumProcessModulesEX = (MyEnumProcessModulesEX)GetProcAddress(GetModuleHandle("Psapi.dll"), "EnumProcessModules"); 97 | int er = EnumProcessModules(m_hProcess, hAllModule, 1000, (PDWORD)&dwNeed); 98 | int count = dwNeed / sizeof(DWORD); 99 | 100 | for (int i = 0; i < count; i++) 101 | { 102 | TCHAR tmp[MAX_PATH]; 103 | //GetModuleFileNameEx(m_hProcess, hAllModule[i], tmp, MAX_PATH); // use GetModuleFileName 會得到亂碼 104 | //MyGetModuleFileNameEX GetModuleFileNameEXX; 105 | //GetModuleFileNameEXX = (MyGetModuleFileNameEX)GetProcAddress(GetModuleHandle("Psapi.dll"), "GetModuleFileNameEx"); 106 | GetModuleFileNameEx(m_hProcess, hAllModule[i], tmp, MAX_PATH); 107 | if (hAllModule[i] == NULL) continue; 108 | 109 | Module mTmp; 110 | mTmp.m_strPath = ""; 111 | mTmp.m_strPath += tmp; 112 | mTmp.m_dwAddr = (DWORD)(hAllModule[i]); 113 | mTmp.m_strName = mTmp.m_strPath.substr( mTmp.m_strPath.find_last_of("\\")+1); 114 | 115 | m_vecModule.Push_Back( mTmp ); 116 | } // for 117 | 118 | delete[] hAllModule; 119 | CloseProcessHandle(); 120 | return true; 121 | } 122 | 123 | void Process::OpenProcessHandle() { 124 | runAsDbg(); 125 | m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, m_dwPid); 126 | //if (m_hProcess == NULL) MessageBox(NULL, "PRO FAILED", "", MB_OK); 127 | } 128 | 129 | void Process::CloseProcessHandle() 130 | { 131 | CloseHandle(m_hProcess); 132 | m_hProcess = NULL; 133 | } 134 | 135 | bool Process::Repair(const char* str_DLL, const char* str_FuncName, DWORD dw_BeginAddr, int length ) 136 | { 137 | //MessageBox(NULL, str_DLL, str_FuncName, MB_OK); 138 | 139 | OpenProcessHandle(); 140 | HANDLE hProcessDLL = GetModuleAddr(str_DLL); // get process module address 141 | if (hProcessDLL == NULL) { // ensure the program has been load this dll. 142 | MessageBox(NULL, "Process has been closed", m_strName.c_str(), MB_OK); 143 | CloseHandle(hProcessDLL); 144 | CloseProcessHandle(); 145 | return false; 146 | } // if 147 | 148 | CloseHandle(hProcessDLL); 149 | HMODULE hDLL = GetModuleHandle(str_DLL); 150 | bool b_NeedFreeLib = false; 151 | if (hDLL == NULL) { 152 | LoadLibraryA(str_DLL); 153 | b_NeedFreeLib = true; 154 | hDLL = GetModuleHandle(str_DLL); 155 | if (hDLL == NULL) 156 | { 157 | MessageBox(NULL, str_DLL, "Can't find this module.", MB_OK); 158 | CloseProcessHandle(); 159 | return false; 160 | } // if 161 | } // if 162 | LPVOID lp_Func = GetProcAddress(GetModuleHandle(str_DLL), str_FuncName); 163 | if (!lp_Func) 164 | { 165 | MessageBox(NULL, str_FuncName, "Can't find this function.", MB_OK); 166 | CloseProcessHandle(); 167 | return false; 168 | } // if 169 | 170 | 171 | BYTE* code = new BYTE[length+1]; 172 | memcpy( code, (LPVOID)(dw_BeginAddr), length ); 173 | DWORD dw_Old, dw_Bkp; 174 | VirtualProtect((LPVOID)(dw_BeginAddr), length, PAGE_EXECUTE_READWRITE, (PDWORD)&dw_Old); 175 | BOOL b_result = WriteProcessMemory(m_hProcess, (LPVOID)(dw_BeginAddr), code, length, NULL); 176 | VirtualProtect((LPVOID)(dw_BeginAddr), length, dw_Old, (PDWORD)&dw_Bkp); 177 | delete[] code; 178 | if (!b_result) 179 | { 180 | MessageBox(NULL, "repair failed", "ERROR", MB_OK); 181 | if (b_NeedFreeLib) FreeLibrary(hDLL); 182 | CloseProcessHandle(); 183 | return false; 184 | } // if 185 | 186 | if (b_NeedFreeLib) FreeLibrary(hDLL); 187 | CloseProcessHandle(); 188 | return true; 189 | } 190 | 191 | HANDLE Process::GetModuleAddr(const char* lps_ModuleName) 192 | { 193 | MODULEENTRY32 mod_ModuleEntry = { 0 }; // Describes an entry from a list of the modules belonging to the specified process. 194 | HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_dwPid); // Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes. 195 | if (!hSnapShot) return NULL; 196 | mod_ModuleEntry.dwSize = sizeof(mod_ModuleEntry); 197 | BOOL b_runModule = Module32First( hSnapShot, &mod_ModuleEntry ); 198 | while (b_runModule) 199 | { 200 | if (strcmp(mod_ModuleEntry.szModule, lps_ModuleName) == 0) 201 | { 202 | CloseHandle(hSnapShot); 203 | return mod_ModuleEntry.modBaseAddr; 204 | } // if 205 | 206 | b_runModule = Module32Next( hSnapShot, &mod_ModuleEntry ); 207 | } // while 208 | 209 | CloseHandle(hSnapShot); 210 | return NULL; 211 | } 212 | 213 | void Process::runAsDbg() 214 | { 215 | HANDLE hCur = NULL; 216 | BOOL success = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hCur); 217 | if (success) 218 | { 219 | TOKEN_PRIVILEGES tp; 220 | tp.PrivilegeCount = 1; 221 | LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); 222 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 223 | AdjustTokenPrivileges(hCur, FALSE, &tp, sizeof(tp), NULL, NULL); 224 | CloseHandle(hCur); 225 | } 226 | } 227 | 228 | HWND g_hWnd = NULL; 229 | BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) 230 | { 231 | if (!hwnd) return TRUE; 232 | DWORD lpdwProcessId; 233 | GetWindowThreadProcessId(hwnd, (PDWORD)&lpdwProcessId); 234 | 235 | 236 | if (lpdwProcessId == lParam) 237 | { 238 | g_hWnd = hwnd; 239 | return FALSE; 240 | } 241 | return TRUE; 242 | } 243 | 244 | void Process::GetHwndByPid() 245 | { 246 | g_hWnd = NULL; 247 | EnumWindows(MyEnumWindowsProc, m_dwPid); 248 | m_hWnd = g_hWnd; 249 | 250 | } 251 | 252 | void Process::GetPath() 253 | { 254 | OpenProcessHandle(); 255 | TCHAR path[MAX_PATH]; 256 | if (GetModuleFileNameEx(m_hProcess, NULL, path, MAX_PATH) == 0) 257 | { 258 | return; 259 | } // if 260 | 261 | CloseProcessHandle(); 262 | m_strPath = path; 263 | } 264 | 265 | void Process::GetIcon() 266 | { 267 | 268 | GetHwndByPid(); 269 | HICON iconHandle = (HICON)::SendMessage(m_hWnd, WM_GETICON, ICON_SMALL2, 0); 270 | if (!iconHandle) 271 | iconHandle = (HICON)::SendMessage(m_hWnd, WM_GETICON, ICON_SMALL, 0); 272 | if (!iconHandle) 273 | iconHandle = (HICON)::SendMessage(m_hWnd, WM_GETICON, ICON_BIG, 0); 274 | 275 | 276 | if (!iconHandle) 277 | { 278 | HICON h_Big; 279 | ExtractIconEx(m_strPath.c_str(), 0, &h_Big, &m_hIcon, 1); 280 | } 281 | else m_hIcon = iconHandle; 282 | } 283 | 284 | /* 285 | IMAGE_EXPORT_DIRECTORY STRUCT【導出表,共40字節】 286 | { 287 | DWORD特性;未使用,總是定義為0 288 | DWORD TimeDateStamp;文件生成時間 289 | WORD MajorVersion;未使用,總是定義為0 290 | WORD MinorVersion;未使用,總是定義為0 291 | DWORD名稱;模塊的真實名稱 292 | DWORD基地;基數,加上序數就是函數地址數組的索引值 293 | DWORD NumberOfFunctions;導出函數的總數 294 | DWORD NumberOfNames;以名稱方式導出的函數的總數 295 | DWORD AddressOfFunctions;指向輸出函數地址的RVA 296 | DWORD AddressOfNames;指向輸出函數名字的RVA 297 | DWORD AddressOfNameOrdinals;指向輸出函數序號的RVA 298 | }; IMAGE_EXPORT_DIRECTORY ENDS 299 | */ 300 | void bytes2String(byte* arr, int stratIndex, int arrSize, char* strBytes) 301 | { 302 | for (int i = stratIndex; i < arrSize; i++) 303 | { 304 | strBytes[i] = (unsigned char)arr[i]; 305 | } // for 306 | 307 | strBytes[arrSize] = '\0'; 308 | } // void 309 | 310 | bool Process::compareFunction(CodeSeg& csdSampleCode, DWORD funcAddr, DWORD nextFuncAddr) 311 | { 312 | SIZE_T lpRead; 313 | DWORD dwSize = nextFuncAddr - funcAddr; 314 | if (dwSize <= 0) 315 | { 316 | MessageBox(NULL, "length of function is wrong.", "ERROR", MB_OK); 317 | return true; 318 | } // if 319 | else if (m_hProcess == NULL) 320 | { 321 | MessageBox(NULL, "Didn't open the process.", "ERROR", MB_OK); 322 | return true; 323 | } // else if 324 | 325 | byte* btCode = new byte[dwSize]; 326 | ReadProcessMemory(m_hProcess, (LPVOID)(funcAddr), btCode, dwSize, &lpRead); 327 | uchar* btOriginCode = (uchar*)funcAddr; 328 | 329 | CodeSeg* csdCode = new CodeSeg(); 330 | csdCode->m_iLength = 0; 331 | csdCode->m_Module.m_dwAddr = csdSampleCode.m_Module.m_dwAddr; 332 | csdCode->m_Proc.m_dwAddr = csdSampleCode.m_Proc.m_dwAddr; 333 | csdCode->m_Module.m_strName = csdSampleCode.m_Module.m_strName; 334 | csdCode->m_Proc.m_strName = csdSampleCode.m_Proc.m_strName; 335 | 336 | int i_recordCounts = 0, i_zeroCount = 0; 337 | ulong cmdLength; 338 | t_disasm da_Origin, da_New; 339 | 340 | for (int i = 0; i < dwSize; i += cmdLength) 341 | { 342 | cmdLength = Disasm((uchar*)(btOriginCode + i), dwSize - i, (DWORD)(btOriginCode + i), &da_Origin, DA_TEXT, NULL, NULL); 343 | if (cmdLength == 0 ) 344 | { 345 | break; 346 | } 347 | 348 | if (da_Origin.errors > 0 || da_Origin.warnings > 0) 349 | { 350 | continue; 351 | } 352 | 353 | 354 | cmdLength = Disasm((uchar*)(btCode + i), dwSize - i, (DWORD)(btOriginCode + i), &da_New, DA_TEXT, NULL, NULL); 355 | 356 | if (cmdLength == 0) 357 | { 358 | break; 359 | } 360 | 361 | if (da_New.errors > 0 || da_Origin.warnings > 0) 362 | { 363 | continue; 364 | } 365 | 366 | if (strcmp(da_New.result, da_Origin.result) != 0 && btCode[i] == 0xe9 ) // (btCode[i] == 0xe9 && btCode[i] != *(btOriginCode + i)) || (btCode[i] == 0xe9 && *(btOriginCode + i) == 0xe9) 367 | { 368 | 369 | csdCode->m_iLength = cmdLength; 370 | csdCode->m_dwCodeAddr = (DWORD)(btOriginCode + i); 371 | csdCode->m_strOriginCode = da_Origin.result; 372 | csdCode->m_strCode = da_New.result; 373 | m_vecDifferentCode.Push_Back(*csdCode); 374 | csdCode = new CodeSeg(); 375 | csdCode->m_Module.m_dwAddr = csdSampleCode.m_Module.m_dwAddr; 376 | csdCode->m_Proc.m_dwAddr = csdSampleCode.m_Proc.m_dwAddr; 377 | csdCode->m_Module.m_strName = csdSampleCode.m_Module.m_strName; 378 | csdCode->m_Proc.m_strName = csdSampleCode.m_Proc.m_strName; 379 | 380 | } // if 381 | 382 | if ((*(btOriginCode + i) == 0x0 && i_zeroCount++ >= 10) || 383 | *(btOriginCode + i) == 0xcc) break; 384 | } // for 385 | 386 | delete csdCode; 387 | 388 | return i_recordCounts > 0 ? false : true; 389 | } 390 | 391 | FARPROC GetProcedureAddress(HANDLE hModule, char* pszProcName) 392 | { 393 | IMAGE_DOS_HEADER* pdhDosHeader = (IMAGE_DOS_HEADER*)hModule; 394 | //Check if valid PE 395 | if (pdhDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0; 396 | 397 | IMAGE_NT_HEADERS* pndNTHeader = (IMAGE_NT_HEADERS*)(pdhDosHeader->e_lfanew + (long)hModule); 398 | if (pndNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0; 399 | 400 | //Traverse the export table to see if we can find the export 401 | IMAGE_EXPORT_DIRECTORY* iedExports = (IMAGE_EXPORT_DIRECTORY*)(pndNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (long)hModule); 402 | long* pNames = (long*)(iedExports->AddressOfNames + (long)hModule); 403 | short wOrdinalIndex = -1; 404 | for (int i = 0; i < iedExports->NumberOfFunctions; i++) 405 | { 406 | char* pszFunctionName = (char *)(pNames[i] + (long)hModule); 407 | 408 | if (lstrcmpi(pszFunctionName, pszProcName) == 0) 409 | { 410 | wOrdinalIndex = i; 411 | break; 412 | } 413 | } 414 | 415 | if (wOrdinalIndex == -1) return 0; 416 | 417 | //wIndex now holds the index of the function name in the names array, which is the index of the ordinal. 418 | //The ordinal also acts as the index of the address 419 | short* pOrdinals = (short*)(iedExports->AddressOfNameOrdinals + (long)hModule); 420 | unsigned long* pAddresses = (unsigned long*)(iedExports->AddressOfFunctions + (long)hModule); 421 | 422 | short wAddressIndex = pOrdinals[wOrdinalIndex]; 423 | return (FARPROC)(pAddresses[wAddressIndex] + (long)hModule); 424 | } 425 | 426 | bool RemoveLoadedDll( char* strDLL ) 427 | { 428 | HANDLE hCur = GetCurrentProcess(); 429 | 430 | } 431 | 432 | bool Process::GetModuleProcs(char* strDLL, CodeSegList* prList ) 433 | { 434 | bool b_NeedRemoveDLL = false; 435 | HMODULE hModule = GetModuleHandle(strDLL); 436 | if (hModule == NULL) 437 | { 438 | b_NeedRemoveDLL = true; 439 | hModule = LoadLibraryA(strDLL); 440 | } // if 441 | 442 | if (hModule == NULL) return false; 443 | uint8_t* dwModuleBase = (uint8_t*)hModule; 444 | IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)dwModuleBase; 445 | if (pDosHeader == NULL) return false; 446 | IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(dwModuleBase + pDosHeader->e_lfanew); 447 | 448 | if (pNTHeaders == NULL) return false; 449 | // 加載器將文件裝入內存並將導入表(導出表)登記的動態鏈接庫(一般是DLL格式)文件一併裝入地址空間, //数据的起始RVA 450 | IMAGE_EXPORT_DIRECTORY* pExpHeader = (IMAGE_EXPORT_DIRECTORY*)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + dwModuleBase); 451 | if (pExpHeader == NULL) return false; 452 | 453 | size_t szModuleSize = pNTHeaders->OptionalHeader.SizeOfImage; 454 | DWORD* pName = (DWORD*)(pExpHeader->AddressOfNames + dwModuleBase); 455 | DWORD* pAddress = (DWORD*)(pExpHeader->AddressOfFunctions + dwModuleBase); // 起始function Address 456 | WORD* pOrdinals = (WORD*)(pExpHeader->AddressOfNameOrdinals + dwModuleBase); // 取得指向輸出函數序號的RVA 457 | 458 | for (int i = 0; i < pExpHeader->NumberOfNames; i++) 459 | { 460 | //WORD wAddressIndex = pOrdinals[i]; // 取得函數序號的內容 461 | const char* pszFunctionName = (const char *)(pName[i] + dwModuleBase); // function name 462 | //MessageBox(NULL, pszFunctionName, "", MB_OK); 463 | CodeSeg mTmp; 464 | mTmp.m_Module.m_strName = strDLL; 465 | mTmp.m_Module.m_dwAddr = (DWORD)dwModuleBase; 466 | mTmp.m_Proc.m_dwAddr = (DWORD)dwModuleBase + pAddress[pOrdinals[i]]; 467 | mTmp.m_Proc.m_strName = pszFunctionName; 468 | prList->Push_Back(mTmp); 469 | 470 | } // for 471 | 472 | prList->Sort(); 473 | CodeSeg mEnd; 474 | mEnd.m_Proc.m_dwAddr = (DWORD)dwModuleBase + szModuleSize; 475 | CodeSegList tmpList; 476 | tmpList.Copy(*prList); 477 | prList->Clear(); 478 | for (int i = 0; i < pExpHeader->NumberOfNames; i++) 479 | { 480 | CodeSeg mCur = tmpList.At(0); 481 | CodeSeg mNext = mEnd; 482 | tmpList.Pop_Front(); 483 | if (tmpList.Size() > 0) 484 | mNext = tmpList.At(0); 485 | mCur.m_Proc.m_dwSize = mNext.m_Proc.m_dwAddr - mCur.m_Proc.m_dwAddr; 486 | if ( mCur.m_Proc.m_dwSize > 0 ) 487 | prList->Push_Back(mCur); 488 | } 489 | 490 | /*TCHAR t[100]; 491 | wsprintf( t, "%x, %x", prList->At(prList->Size()-1).m_Proc.m_dwAddr, szModuleSize); 492 | MessageBox(NULL, t, "", MB_OK);*/ 493 | if (b_NeedRemoveDLL) 494 | FreeLibrary(hModule); 495 | tmpList.Clear(); 496 | if (b_NeedRemoveDLL) 497 | FreeLibrary(hModule); 498 | } 499 | 500 | bool Process::ScanModuleHook(char* strDLL) 501 | { 502 | //ofstream fout("Different.txt"); 503 | 504 | // traverse module function 505 | //if (hModule == NULL) // 非 getAllModule 的方式 506 | //{ 507 | bool b_NeedRemoveDLL = false; 508 | HMODULE hModule = GetModuleHandle(strDLL); 509 | if (hModule == NULL) 510 | { 511 | b_NeedRemoveDLL = true; 512 | hModule = LoadLibraryA(strDLL); 513 | } // if 514 | 515 | if (hModule == NULL) return false; 516 | //} // if PVOID hProcessModuleBaseAddr 517 | //HMODULE hModule = (HMODULE)GetModuleAddr(strDLL); 518 | uint8_t* dwModuleBase = (uint8_t*)hModule; 519 | IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)dwModuleBase; 520 | if (pDosHeader == NULL) return false; 521 | IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(dwModuleBase + pDosHeader->e_lfanew); 522 | 523 | if (pNTHeaders == NULL) return false; 524 | // 加載器將文件裝入內存並將導入表(導出表)登記的動態鏈接庫(一般是DLL格式)文件一併裝入地址空間, //数据的起始RVA 525 | IMAGE_EXPORT_DIRECTORY* pExpHeader = (IMAGE_EXPORT_DIRECTORY*)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + dwModuleBase); 526 | if (pExpHeader == NULL) return false; 527 | 528 | size_t szModuleSize = pNTHeaders->OptionalHeader.SizeOfImage; 529 | DWORD* pName = (DWORD*)(pExpHeader->AddressOfNames + dwModuleBase); 530 | /*TCHAR fuck[100]; 531 | wsprintf( fuck, "%X", pExpHeader->AddressOfNames); 532 | MessageBox(NULL, fuck, "", MB_OK);*/ 533 | DWORD* pAddress = (DWORD*)(pExpHeader->AddressOfFunctions + dwModuleBase); // 起始function Address 534 | WORD* pOrdinals = (WORD*)(pExpHeader->AddressOfNameOrdinals + dwModuleBase); // 取得指向輸出函數序號的RVA 535 | 536 | for (int i = 0; i < pExpHeader->NumberOfNames; i++) 537 | { 538 | //WORD wAddressIndex = pOrdinals[i]; // 取得函數序號的內容 539 | 540 | //DWORD funcAddr = (DWORD)pAddress[wAddressIndex] + (DWORD)dwModuleBase; // function address 541 | //if (funcAddr <= 0 || funcAddr >= (DWORD)hModule + szModuleSize) continue; 542 | //if (pName[i] + dwModuleBase >= dwModuleBase + szModuleSize) continue; 543 | 544 | 545 | const char* pszFunctionName = (const char *)(pName[i] + dwModuleBase); // function name 546 | //MessageBox(NULL, pszFunctionName, "", MB_OK); 547 | Proc mTmp; 548 | mTmp.m_dwAddr = (DWORD)dwModuleBase + pAddress[pOrdinals[i]]; 549 | mTmp.m_strName = pszFunctionName; 550 | procList.Push_Back(mTmp); 551 | 552 | } // for 553 | 554 | //MessageBox(NULL, "STOP2", "", MB_OK); 555 | OpenProcessHandle(); 556 | Preparedisasm(); 557 | procList.Sort(); 558 | Proc mEnd; 559 | mEnd.m_dwAddr = (DWORD)hModule + szModuleSize; 560 | //fout << mEnd.m_dwAddr << endl; 561 | while (procList.Size() > 0 ) 562 | { 563 | Proc mCur = procList.At(0); 564 | Proc mNext = mEnd; 565 | procList.Pop_Front(); 566 | if (procList.Size() > 0 ) 567 | mNext = procList.At(0); 568 | if (mNext.m_dwAddr <= mCur.m_dwAddr) // WTF? two different function has the same address... 569 | { 570 | continue; 571 | } // if 572 | 573 | 574 | CodeSeg csdCode; 575 | csdCode.m_iLength = 0; 576 | csdCode.m_Module.m_strName = strDLL; 577 | csdCode.m_Module.m_dwAddr = (DWORD)hModule; 578 | csdCode.m_Proc.m_dwAddr = mCur.m_dwAddr; 579 | csdCode.m_Proc.m_strName = mCur.m_strName; 580 | if (!compareFunction(csdCode, mCur.m_dwAddr, mNext.m_dwAddr)) 581 | { 582 | 583 | } // if 584 | 585 | } // while 586 | 587 | if (b_NeedRemoveDLL) 588 | FreeLibrary(hModule); 589 | Finishdisasm(); 590 | CloseProcessHandle(); 591 | //fout.close(); 592 | procList.Clear(); 593 | return true; 594 | } 595 | 596 | void Process::GetPermission() 597 | { 598 | 599 | OpenProcessHandle(); 600 | DWORD dwNeed = 0; 601 | HMODULE* hAllModule = new HMODULE[1000]; 602 | //MyEnumProcessModulesEX EnumProcessModulesEX = (MyEnumProcessModulesEX)GetProcAddress(GetModuleHandle("Psapi.dll"), "EnumProcessModules"); 603 | int er = EnumProcessModules(m_hProcess, hAllModule, 1000, (PDWORD)&dwNeed); 604 | int count = dwNeed / sizeof(DWORD); 605 | if (count > 0) 606 | isAllow = true; 607 | else 608 | isAllow = false; 609 | CloseProcessHandle(); 610 | } 611 | 612 | BOOL Is64BitWindows() 613 | { 614 | #if defined(_WIN64) 615 | return TRUE; // 64-bit programs run only on Win64 616 | #elif defined(_WIN32) 617 | // 32-bit programs run on both 32-bit and 64-bit Windows 618 | // so must sniff 619 | BOOL f64 = FALSE; 620 | return IsWow64Process(GetCurrentProcess(), &f64) && f64; 621 | #else 622 | return FALSE; // Win64 does not support Win16 623 | #endif 624 | } 625 | 626 | bool EnumAllProcesses(vector& vec_ProcessList) 627 | { 628 | HANDLE hSnapshot; 629 | PROCESSENTRY32 proc32;// Describes an entry from a list of the processes residing in the system address space when a snapshot was taken. 630 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 631 | if (hSnapshot == NULL) 632 | { 633 | MessageBox(NULL, "get processes failed", "ERROR", MB_OK); 634 | return false; 635 | } // if 636 | 637 | proc32.dwSize = sizeof(proc32); 638 | if (!Process32First(hSnapshot, &proc32)) 639 | { 640 | MessageBox(NULL, "get processes failed", "ERROR", MB_OK); 641 | return false; 642 | } // if 643 | 644 | do 645 | { 646 | if (strlen(proc32.szExeFile) > 0) 647 | { 648 | Process tmp(proc32.th32ProcessID, proc32.szExeFile, NULL); 649 | tmp.GetPath(); 650 | tmp.GetIcon(); 651 | tmp.OpenProcessHandle(); 652 | SYSTEM_INFO si; 653 | GetNativeSystemInfo(&si); 654 | if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_IA64) 655 | { // 64 位操作系统 656 | IsWow64Process(tmp.m_hProcess, &tmp.is32Bit); 657 | } // if 658 | else 659 | { // 32 位操作系统 660 | tmp.is32Bit = true; 661 | } // else 662 | 663 | tmp.GetPermission(); 664 | tmp.Clear(); 665 | vec_ProcessList.push_back(tmp); 666 | } 667 | } while (Process32Next(hSnapshot, &proc32)); 668 | 669 | return true; 670 | } 671 | 672 | bool isModuleBeenLoaded(string strDLL) 673 | { 674 | HMODULE hDLL = GetModuleHandle(strDLL.c_str()); 675 | if (hDLL == NULL) { 676 | LoadLibraryA(strDLL.c_str()); 677 | hDLL = GetModuleHandle(strDLL.c_str()); 678 | if (hDLL == NULL) 679 | { 680 | MessageBox(NULL, strDLL.c_str(), "Can't find this module.", MB_OK); 681 | return true; 682 | } // if 683 | 684 | return false; // need free 685 | } // if 686 | 687 | return true; 688 | } -------------------------------------------------------------------------------- /Process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | using namespace std; 4 | 5 | class Process 6 | { 7 | public: 8 | BOOL isAllow; 9 | BOOL is32Bit; 10 | DWORD m_dwPid; 11 | HWND m_hWnd; 12 | string m_strName; 13 | string m_strPath; 14 | HANDLE m_hProcess; 15 | HICON m_hIcon; 16 | ModuleList m_vecModule; 17 | CodeSegList m_vecDifferentCode; 18 | Process(); 19 | Process(DWORD dw, char* str, HANDLE handle); 20 | ~Process(); 21 | bool Terminate(); 22 | void Copy( Process* src ); 23 | void DeleteDifferentCodeList(); 24 | void Clear(); 25 | void GetPath(); 26 | void GetIcon(); 27 | void OpenProcessHandle(); 28 | void CloseProcessHandle(); 29 | bool Repair(const char* str_DLL, const char* str_FuncName, DWORD dw_BeginAddr, int length); 30 | /*void Free() { 31 | CloseHandle(m_hProcess); 32 | }*/ 33 | bool ScanModuleHook(char* strDLL); 34 | bool GetModuleProcs(char* strDLL, CodeSegList* prList); 35 | bool GetAllModule(); 36 | void GetPermission(); 37 | private: 38 | //BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam); 39 | bool compareFunction(CodeSeg& csdCode, DWORD funcAddr, DWORD nextFuncAddr); 40 | void GetHwndByPid(); 41 | void runAsDbg(); 42 | HANDLE GetModuleAddr(const char* lps_ModuleName ); 43 | 44 | }; 45 | 46 | BOOL Is64BitWindows(); 47 | bool EnumAllProcesses(vector& vec_ProcessList); 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Win32ApiHookDetector 2 | Win32 API Hook偵測 3 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | MFC 程式庫:HookRepairer 專案概觀 3 | =============================================================================== 4 | 5 | 應用程式精靈已經為您建立了這個 HookRepairer 應用程式。這個應用程式不僅示範了使用 MFC 的基本概念,也是您撰寫應用程式的起點。 6 | 7 | 這個檔案包含一份摘要,簡要說明構成 HookRepairer 應用程式的 8 | 所有檔案,它們個別的內容。 9 | 10 | HookRepairer.vcxproj 11 | 這是使用應用程式精靈所產生之 VC++ 專案的主要專案檔。它含有產生該檔案之 Visual C++ 的版本資訊,以及有關使用應用程式精靈所選取之平台、組態和專案功能的資訊。 12 | 13 | HookRepairer.vcxproj.filters 14 | 這是使用應用程式精靈所產生之 VC++ 專案的篩選檔。檔案中含有您專案中檔案與篩選器之間關聯的相關資訊。這項關聯用於 IDE 中以顯示特定節點下具有類似副檔名之檔案的群組 (例如,".cpp" 檔案會與 "Source Files" 篩選器相關聯)。 15 | 16 | HookRepairer.h 17 | 這是應用程式的主要標頭檔。 18 | 它包含了特定標頭 (包括 Resource.h),並宣告 CHookRepairerApp 應用程式類別。 19 | 20 | HookRepairer.cpp 21 | 這是含有應用程式類別 CHookRepairerApp 的主要應用程式原始程式檔。 22 | 23 | HookRepairer.rc 24 | 這是程式所用的所有 Microsoft Windows 資源的列表。它含有儲存在 RES 子目錄中的圖示、點陣圖和游標。您可以直接在 Microsoft Visual C++ 內編輯這個檔案。您的專案資源是在 1028。 25 | 26 | res\HookRepairer.ico 27 | 這是用來做為應用程式圖示的圖示檔。這個圖示是包含在主要資源檔 HookRepairer.rc 中。 28 | 29 | res\HookRepairer.rc2 30 | 這個檔案包含 Microsoft Visual C++ 無法編輯的資源。您應該將所有資源編輯器無法編輯的資源放到這個檔案。 31 | 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | 35 | 應用程式精靈會建立一個對話方塊類別: 36 | 37 | HookRepairerDlg.h、HookRepairerDlg.cpp - 對話方塊 38 | 這些檔案包含您的 CHookRepairerDlg 類別。這個類別會定義應用程式主對話方塊的行為。對話方塊的範本是在可於 Microsoft Visual C++ 編輯的 HookRepairer.rc 中。 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | 42 | 其他功能: 43 | 44 | ActiveX 控制項 45 | 應用程式包括使用 ActiveX 控制項的支援。 46 | 47 | ///////////////////////////////////////////////////////////////////////////// 48 | 49 | 其他標準檔案: 50 | 51 | StdAfx.h, StdAfx.cpp 52 | 這些檔案是用來建置名為 HookRepairer.pch 的先行編譯標頭 (PCH) 檔,以及名為 StdAfx.obj 的先行編譯型別檔。 53 | 54 | Resource.h 55 | 這是標準標頭檔,它定義新的資源 ID。Microsoft Visual C++ 會讀取和更新這個檔案。 56 | 57 | HookRepairer.manifest 58 | Windows XP 會使用應用程式資訊清單檔案來描述特定並存組件版本的應用程式相依性。載入器會使用這項資訊載入組件快取中的適當組件,或應用程式中的私用組件。應用程式資訊清單可能隨附用於轉散發,做為與應用程式可執行檔相同資料夾中所安裝的外部 .manifest 檔案,或是以資源的形式隨附在可執行檔中。 59 | ///////////////////////////////////////////////////////////////////////////// 60 | 61 | 其他注意事項: 62 | 63 | 應用程式精靈使用 "TODO:" 來指示您應該加入或自訂的原始程式碼部分。 64 | 65 | 如果您的應用程式使用 MFC 的共用 DLL,您將需要轉散發 MFC DLL。如果您的應用程式採用不同於作業系統地區設定的語言,您還必須轉散發對應的當地語系化資源 mfc110XXX.DLL。 66 | 如需這兩個主題的詳細資訊,請參閱 MSDN 文件中轉散發 Visual C++ 應用程式的章節。 67 | 68 | ///////////////////////////////////////////////////////////////////////////// 69 | -------------------------------------------------------------------------------- /SearchDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/SearchDlg.cpp -------------------------------------------------------------------------------- /SearchDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/SearchDlg.h -------------------------------------------------------------------------------- /TAB1.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/TAB1.cpp -------------------------------------------------------------------------------- /TAB1.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/TAB1.h -------------------------------------------------------------------------------- /TAB2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/TAB2.cpp -------------------------------------------------------------------------------- /TAB2.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/TAB2.h -------------------------------------------------------------------------------- /TAB3.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/TAB3.cpp -------------------------------------------------------------------------------- /TAB3.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxz456999/Win32ApiHookDetector/712e373859003d076fa37ff382ab3e062ced4085/TAB3.h -------------------------------------------------------------------------------- /WebPage.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////// 2 | // By Eugene Khodakovsky // 3 | // April,2002 // 4 | // Eugene@cpplab.com // 5 | // Last Update: April, 2002 // 6 | ///////////////////////////////////////////////////////////////// 7 | 8 | #include "stdafx.h" 9 | #include "JSCall.h" 10 | #include "WebPage.h" 11 | 12 | #ifdef _DEBUG 13 | #undef THIS_FILE 14 | static char THIS_FILE[]=__FILE__; 15 | #define new DEBUG_NEW 16 | #endif 17 | 18 | #define CHECK_POINTER(p)\ 19 | ATLASSERT(p != NULL);\ 20 | if(p == NULL)\ 21 | {\ 22 | ShowError("NULL pointer");\ 23 | return false;\ 24 | } 25 | 26 | const CString GetSystemErrorMessage(DWORD dwError) 27 | { 28 | CString strError; 29 | LPTSTR lpBuffer; 30 | 31 | if(!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 32 | NULL, dwError, 33 | MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), 34 | (LPTSTR) &lpBuffer, 0, NULL)) 35 | 36 | { 37 | strError = "FormatMessage Netive Error" ; 38 | } 39 | else 40 | { 41 | strError = lpBuffer; 42 | LocalFree(lpBuffer); 43 | } 44 | return strError; 45 | } 46 | 47 | CString GetNextToken(CString& strSrc, const CString strDelim,bool bTrim, bool bFindOneOf) 48 | { 49 | CString strToken; 50 | int idx = bFindOneOf? strSrc.FindOneOf(strDelim) : strSrc.Find(strDelim); 51 | if(idx != -1) 52 | { 53 | strToken = strSrc.Left(idx); 54 | strSrc = strSrc.Right(strSrc.GetLength() - (idx + 1) ); 55 | } 56 | else 57 | { 58 | strToken = strSrc; 59 | strSrc.Empty(); 60 | } 61 | if(bTrim) 62 | { 63 | strToken.TrimLeft(); 64 | strToken.TrimRight(); 65 | } 66 | return strToken; 67 | } 68 | 69 | ////////////////////////////////////////////////////////////////////// 70 | // Construction/Destruction 71 | ////////////////////////////////////////////////////////////////////// 72 | 73 | CWebPage::CWebPage() 74 | { 75 | } 76 | 77 | CWebPage::~CWebPage() 78 | { 79 | 80 | } 81 | 82 | bool CWebPage::SetDocument(IDispatch* pDisp) 83 | { 84 | CHECK_POINTER(pDisp); 85 | 86 | m_spDoc = NULL; 87 | 88 | CComPtr spDisp = pDisp; 89 | 90 | HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc); 91 | if(FAILED(hr)) 92 | { 93 | ShowError("Failed to get HTML document COM object"); 94 | return false; 95 | } 96 | return true; 97 | } 98 | 99 | bool CWebPage::GetJScript(CComPtr& spDisp) 100 | { 101 | CHECK_POINTER(m_spDoc); 102 | HRESULT hr = m_spDoc->get_Script(&spDisp); 103 | ATLASSERT(SUCCEEDED(hr)); 104 | return SUCCEEDED(hr); 105 | } 106 | 107 | bool CWebPage::GetJScripts(CComPtr& spColl) 108 | { 109 | CHECK_POINTER(m_spDoc); 110 | HRESULT hr = m_spDoc->get_scripts(&spColl); 111 | ATLASSERT(SUCCEEDED(hr)); 112 | return SUCCEEDED(hr); 113 | } 114 | 115 | bool CWebPage::CallJScript(const CString strFunc,CComVariant* pVarResult) 116 | { 117 | CStringArray paramArray; 118 | return CallJScript(strFunc,paramArray,pVarResult); 119 | } 120 | 121 | bool CWebPage::CallJScript(const CString strFunc,const CString strArg1,CComVariant* pVarResult) 122 | { 123 | CStringArray paramArray; 124 | paramArray.Add(strArg1); 125 | return CallJScript(strFunc,paramArray,pVarResult); 126 | } 127 | 128 | bool CWebPage::CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,CComVariant* pVarResult) 129 | { 130 | CStringArray paramArray; 131 | paramArray.Add(strArg1); 132 | paramArray.Add(strArg2); 133 | return CallJScript(strFunc,paramArray,pVarResult); 134 | } 135 | 136 | bool CWebPage::CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,const CString strArg3,CComVariant* pVarResult) 137 | { 138 | CStringArray paramArray; 139 | paramArray.Add(strArg1); 140 | paramArray.Add(strArg2); 141 | paramArray.Add(strArg3); 142 | return CallJScript(strFunc,paramArray,pVarResult); 143 | } 144 | 145 | bool CWebPage::CallJScript(const CString strFunc, const CStringArray& paramArray,CComVariant* pVarResult) 146 | { 147 | CComPtr spScript; 148 | if(!GetJScript(spScript)) 149 | { 150 | ShowError("Cannot GetScript"); 151 | return false; 152 | } 153 | CComBSTR bstrMember(strFunc); 154 | DISPID dispid = NULL; 155 | HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1, 156 | LOCALE_SYSTEM_DEFAULT,&dispid); 157 | if(FAILED(hr)) 158 | { 159 | ShowError(GetSystemErrorMessage(hr)); 160 | return false; 161 | } 162 | 163 | const int arraySize = paramArray.GetSize(); 164 | 165 | DISPPARAMS dispparams; 166 | memset(&dispparams, 0, sizeof dispparams); 167 | dispparams.cArgs = arraySize; 168 | dispparams.rgvarg = new VARIANT[dispparams.cArgs]; 169 | 170 | for( int i = 0; i < arraySize; i++) 171 | { 172 | CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); // back reading 173 | bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); 174 | dispparams.rgvarg[i].vt = VT_BSTR; 175 | } 176 | dispparams.cNamedArgs = 0; 177 | 178 | EXCEPINFO excepInfo; 179 | memset(&excepInfo, 0, sizeof excepInfo); 180 | CComVariant vaResult; 181 | UINT nArgErr = (UINT)-1; // initialize to invalid arg 182 | 183 | hr = spScript->Invoke(dispid,IID_NULL,0, 184 | DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr); 185 | 186 | delete [] dispparams.rgvarg; 187 | if(FAILED(hr)) 188 | { 189 | ShowError(GetSystemErrorMessage(hr)); 190 | return false; 191 | } 192 | 193 | if(pVarResult) 194 | { 195 | *pVarResult = vaResult; 196 | } 197 | return true; 198 | } 199 | 200 | // returned java script function name, input string is truncating 201 | CString CWebPage::ScanJScript(CString& strAText, CStringArray& args) 202 | { 203 | args.RemoveAll(); 204 | CString strDelim(" \n\r\t"),strSrc(strAText); 205 | bool bFound = false; 206 | while(!strSrc.IsEmpty()) 207 | { 208 | CString strStart = GetNextToken(strSrc,strDelim); 209 | if(strStart == "function") 210 | { 211 | bFound = true; 212 | break; 213 | } 214 | if(strStart == "/*") 215 | { 216 | // Skip comments 217 | while(!strSrc.IsEmpty()) 218 | { 219 | CString strStop = GetNextToken(strSrc,strDelim); 220 | if(strStop == "*/") 221 | { 222 | break; 223 | } 224 | } 225 | } 226 | } 227 | 228 | if(!bFound) 229 | return ""; 230 | 231 | CString strFunc = GetNextToken(strSrc,"(",true); 232 | CString strArgs = GetNextToken(strSrc,")",true); 233 | 234 | // Parse arguments 235 | CString strArg; 236 | while(!(strArg = GetNextToken(strArgs,",")).IsEmpty()) 237 | args.Add(strArg); 238 | 239 | strAText= strSrc; 240 | return strFunc; 241 | } 242 | 243 | -------------------------------------------------------------------------------- /WebPage.h: -------------------------------------------------------------------------------- 1 | // WebPage.h: interface for the CWebPage class. 2 | // 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | #if !defined(AFX_WEBPAGE_H__AEBD50B8_EE66_40AB_8B92_C4EECB9BCD22__INCLUDED_) 6 | #define AFX_WEBPAGE_H__AEBD50B8_EE66_40AB_8B92_C4EECB9BCD22__INCLUDED_ 7 | 8 | #if _MSC_VER > 1000 9 | #pragma once 10 | #endif // _MSC_VER > 1000 11 | 12 | #include 13 | #include 14 | 15 | class CWebPage 16 | { 17 | public: 18 | CWebPage(); 19 | virtual ~CWebPage(); 20 | 21 | bool SetDocument(IDispatch* pDisp); 22 | LPDISPATCH GetHtmlDocument() const; 23 | const CString GetLastError() const; 24 | bool GetJScript(CComPtr& spDisp); 25 | bool GetJScripts(CComPtr& spColl); 26 | 27 | CString ScanJScript(CString& strAText, CStringArray& args); 28 | 29 | bool CallJScript(const CString strFunc,CComVariant* pVarResult = NULL); 30 | bool CallJScript(const CString strFunc,const CString strArg1,CComVariant* pVarResult = NULL); 31 | bool CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,CComVariant* pVarResult = NULL); 32 | bool CallJScript(const CString strFunc,const CString strArg1,const CString strArg2,const CString strArg3,CComVariant* pVarResult = NULL); 33 | bool CallJScript(const CString strFunc,const CStringArray& paramArray,CComVariant* pVarResult = NULL); 34 | 35 | protected: 36 | 37 | 38 | void ShowError(LPCSTR lpszText); 39 | 40 | protected: 41 | 42 | CComPtr m_spDoc; 43 | CString m_strError; 44 | 45 | }; 46 | 47 | inline 48 | void CWebPage::ShowError(LPCSTR lpszText) 49 | { 50 | m_strError = "JSCall Error:\n" + CString(lpszText); 51 | } 52 | inline 53 | const CString CWebPage::GetLastError() const 54 | { 55 | return m_strError; 56 | } 57 | inline 58 | LPDISPATCH CWebPage::GetHtmlDocument() const 59 | { 60 | return m_spDoc; 61 | } 62 | 63 | CString GetNextToken(CString& strSrc, const CString strDelim,bool bTrim = false, bool bFindOneOf = true); 64 | 65 | #endif // !defined(AFX_WEBPAGE_H__AEBD50B8_EE66_40AB_8B92_C4EECB9BCD22__INCLUDED_) 66 | -------------------------------------------------------------------------------- /disasm.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // // 3 | // OllyDbg Disassembling Engine v2.01 // 4 | // // 5 | // Copyright (c) 2007-2013 Oleh Yuschuk, ollydbg@t-online.de // 6 | // // 7 | // This code is part of the OllyDbg Disassembler v2.01 // 8 | // // 9 | // Disassembling engine is free software; you can redistribute it and/or // 10 | // modify it under the terms of the GNU General Public License as published // 11 | // by the Free Software Foundation; either version 3 of the License, or (at // 12 | // your option) any later version. // 13 | // // 14 | // This code is distributed in the hope that it will be useful, but WITHOUT // 15 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // 16 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // 17 | // more details. // 18 | // // 19 | // You should have received a copy of the GNU General Public License along // 20 | // with this program. If not, see . // 21 | // // 22 | //////////////////////////////////////////////////////////////////////////////// 23 | 24 | 25 | //////////////////////////////////////////////////////////////////////////////// 26 | // // 27 | // This is a fast disassembler that can be used to determine the length of // 28 | // the binary 80x86 32-bit command and its attributes, to convert it to the // 29 | // human-readable text form, highlight its operands, and create hexadecimal // 30 | // dump of the binary command. // 31 | // // 32 | // It is a stripped down version of the disassembler used by OllyDbg 2.01. // 33 | // It can't analyse and comment the contents of the operands, or predict the // 34 | // results of the command execution. Analysis-dependent features are not // 35 | // included, too. Most other features are kept. // 36 | // // 37 | // Disassembler supports integer, FPU, MMX, 3DNow, SSE1-SSE4.1 and AVX // 38 | // instructions. 64-bit mode, AVX2, FMA and XOP are not (yet) supported. // 39 | // // 40 | // This code can be compiled either in ASCII or UNICODE mode. It is reentrant // 41 | // (thread-safe, feature not available in the original OllyDbg code). // 42 | // // 43 | // Typical operation speed on 3-GHz Phenom II in MASM mode is: // 44 | // // 45 | // Command length and info: 130 ns/command (7,700,000 commands/s) // 46 | // Disassembly: 290 ns/command (3,400,000 commands/s) // 47 | // Disassembly, dump, highlighting: 350 ns/command (2,800,000 commands/s) // 48 | // // 49 | //////////////////////////////////////////////////////////////////////////////// 50 | 51 | 52 | //////////////////////////////////////////////////////////////////////////////// 53 | ////////////// PREFERRED SETTINGS AND FIXES FOR BORLAND COMPILERS ////////////// 54 | 55 | #ifdef __BORLANDC__ 56 | #pragma option -a1 // Byte alignment 57 | #pragma option -w-pin // Disable "partially bracketed" warning 58 | // Redefinition of MAKELONG removes nasty warning under Borland Builder 4.0: 59 | // boolean OR in one row with arithmetical shift. 60 | #undef MAKELONG 61 | #define MAKELONG(lo,hi) ((LONG)(((WORD)(lo))|(((DWORD)((WORD)(hi)))<<16))) 62 | #endif 63 | 64 | #define MAKEWP(lo,hi) ((WPARAM)MAKELONG(lo,hi)) 65 | #define MAKELP(lo,hi) ((LPARAM)MAKELONG(lo,hi)) 66 | 67 | #define LOINT(l) ((signed short)((WORD)(l))) 68 | #define HIINT(l) ((signed short)(((DWORD)(l)>>16) & 0xFFFF)) 69 | 70 | #ifndef FIELD_OFFSET 71 | #define FIELD_OFFSET(type,field) ((long)&(((type *)0)->field)) 72 | #endif 73 | 74 | 75 | //////////////////////////////////////////////////////////////////////////////// 76 | 77 | #define TEXTLEN 256 // Max length of text string 78 | #define SHORTNAME 32 // Max length of short or module name 79 | 80 | #ifdef UNICODE 81 | #define tchar wchar_t // Or replace it with TCHAR 82 | #define T(x) L##x 83 | #define tstrlen wcslen 84 | #define tstrcpy wcscpy 85 | #define tstrcmp wcscmp 86 | #define tstrlwr _wcslwr 87 | #define tsprintf swprintf 88 | #define ttolower towlower 89 | #else 90 | #define tchar char 91 | #define T(x) x 92 | #define tstrlen strlen 93 | #define tstrcpy strcpy 94 | #define tstrcmp strcmp 95 | #define tstrlwr strlwr 96 | #define tsprintf sprintf 97 | #define ttolower tolower 98 | #endif 99 | 100 | #define NOPERAND 4 // Maximal allowed number of operands 101 | #define NREG 8 // Number of registers (of any type) 102 | #define NSEG 6 // Number of valid segment registers 103 | #define MAXCMDSIZE 16 // Maximal length of valid 80x86 command 104 | #define NEGLIMIT (-16384) // Limit to decode offsets as negative 105 | #define DECLIMIT 16384 // Limit to decode constants as decimal 106 | 107 | typedef unsigned char uchar; // Unsigned character (byte) 108 | typedef unsigned short ushort; // Unsigned short 109 | typedef unsigned int uint; // Unsigned integer 110 | typedef unsigned long ulong; // Unsigned long 111 | 112 | // CMDMASK can be used to balance between the necessary memory size and the 113 | // disassembly time. 114 | #define CMDMASK 0x3FFF // Search mask for Disassembler, 2**n-1 115 | #define NCHAIN 44300 // Max allowed number of chain links 116 | 117 | // Registers. 118 | #define REG_UNDEF (-1) // Codes of general purpose registers 119 | #define REG_EAX 0 120 | #define REG_ECX 1 121 | #define REG_EDX 2 122 | #define REG_EBX 3 123 | #define REG_ESP 4 124 | #define REG_EBP 5 125 | #define REG_ESI 6 126 | #define REG_EDI 7 127 | 128 | #define REG_AL 0 // Symbolic indices of 8-bit registers 129 | #define REG_CL 1 130 | #define REG_DL 2 131 | #define REG_BL 3 132 | #define REG_AH 4 133 | #define REG_CH 5 134 | #define REG_DH 6 135 | #define REG_BH 7 136 | 137 | #define SEG_UNDEF (-1) // Codes of segment/selector registers 138 | #define SEG_ES 0 139 | #define SEG_CS 1 140 | #define SEG_SS 2 141 | #define SEG_DS 3 142 | #define SEG_FS 4 143 | #define SEG_GS 5 144 | 145 | // Command highlighting. 146 | #define DRAW_PLAIN '.' //0x0000000C // Plain commands 147 | #define DRAW_JUMP '>' //0x0000000D // Unconditional jump commands 148 | #define DRAW_CJMP '?' //0x0000000E // Conditional jump commands 149 | #define DRAW_PUSHPOP '=' //0x0000000F // PUSH/POP commands 150 | #define DRAW_CALL '@' //0x00000010 // CALL commands 151 | #define DRAW_RET '<' //0x00000011 // RET commands 152 | #define DRAW_FPU '1' //0x00000012 // FPU, MMX, 3DNow! and SSE commands 153 | #define DRAW_SUSPECT '!' //0x00000013 // Bad, system and privileged commands 154 | // Operand highlighting. 155 | #define DRAW_IREG 'R' //0x00000018 // General purpose registers 156 | #define DRAW_FREG 'F' //0x00000019 // FPU, MMX and SSE registers 157 | #define DRAW_SYSREG 'S' //0x0000001A // Segment and system registers 158 | #define DRAW_STKMEM 'K' //0x0000001B // Memory accessed over ESP or EBP 159 | #define DRAW_MEM 'M' //0x0000001C // Any other memory 160 | #define DRAW_CONST 'C' //0x0000001E // Constant 161 | 162 | #define D_NONE 0x00000000 // No special features 163 | // General type of command, only one is allowed. 164 | #define D_CMDTYPE 0x0000001F // Mask to extract type of command 165 | #define D_CMD 0x00000000 // Ordinary (none of listed below) 166 | #define D_MOV 0x00000001 // Move to or from integer register 167 | #define D_MOVC 0x00000002 // Conditional move to integer register 168 | #define D_SETC 0x00000003 // Conditional set integer register 169 | #define D_TEST 0x00000004 // Used to test data (CMP, TEST, AND...) 170 | #define D_STRING 0x00000005 // String command with REPxxx prefix 171 | #define D_JMP 0x00000006 // Unconditional near jump 172 | #define D_JMPFAR 0x00000007 // Unconditional far jump 173 | #define D_JMC 0x00000008 // Conditional jump on flags 174 | #define D_JMCX 0x00000009 // Conditional jump on (E)CX (and flags) 175 | #define D_PUSH 0x0000000A // PUSH exactly 1 (d)word of data 176 | #define D_POP 0x0000000B // POP exactly 1 (d)word of data 177 | #define D_CALL 0x0000000C // Plain near call 178 | #define D_CALLFAR 0x0000000D // Far call 179 | #define D_INT 0x0000000E // Interrupt 180 | #define D_RET 0x0000000F // Plain near return from call 181 | #define D_RETFAR 0x00000010 // Far return or IRET 182 | #define D_FPU 0x00000011 // FPU command 183 | #define D_MMX 0x00000012 // MMX instruction, incl. SSE extensions 184 | #define D_3DNOW 0x00000013 // 3DNow! instruction 185 | #define D_SSE 0x00000014 // SSE instruction 186 | #define D_IO 0x00000015 // Accesses I/O ports 187 | #define D_SYS 0x00000016 // Legal but useful in system code only 188 | #define D_PRIVILEGED 0x00000017 // Privileged (non-Ring3) command 189 | #define D_AVX 0x00000018 // AVX instruction 190 | #define D_XOP 0x00000019 // AMD instruction with XOP prefix 191 | #define D_DATA 0x0000001C // Data recognized by Analyser 192 | #define D_PSEUDO 0x0000001D // Pseudocommand, for search models only 193 | #define D_PREFIX 0x0000001E // Standalone prefix 194 | #define D_BAD 0x0000001F // Bad or unrecognized command 195 | // Additional parts of the command. 196 | #define D_SIZE01 0x00000020 // Bit 0x01 in last cmd is data size 197 | #define D_POSTBYTE 0x00000040 // Command continues in postbyte 198 | // For string commands, either long or short form can be selected. 199 | #define D_LONGFORM 0x00000080 // Long form of string command 200 | // Decoding of some commands depends on data or address size. 201 | #define D_SIZEMASK 0x00000F00 // Mask for data/address size dependence 202 | #define D_DATA16 0x00000100 // Requires 16-bit data size 203 | #define D_DATA32 0x00000200 // Requires 32-bit data size 204 | #define D_ADDR16 0x00000400 // Requires 16-bit address size 205 | #define D_ADDR32 0x00000800 // Requires 32-bit address size 206 | // Prefixes that command may, must or must not possess. 207 | #define D_MUSTMASK 0x0000F000 // Mask for fixed set of prefixes 208 | #define D_NOMUST 0x00000000 // No obligatory prefixes (default) 209 | #define D_MUST66 0x00001000 // (SSE,AVX) Requires 66, no F2 or F3 210 | #define D_MUSTF2 0x00002000 // (SSE,AVX) Requires F2, no 66 or F3 211 | #define D_MUSTF3 0x00003000 // (SSE,AVX) Requires F3, no 66 or F2 212 | #define D_MUSTNONE 0x00004000 // (MMX,SSE,AVX) Requires no 66, F2, F3 213 | #define D_NEEDF2 0x00005000 // (SSE,AVX) Requires F2, no F3 214 | #define D_NEEDF3 0x00006000 // (SSE,AVX) Requires F3, no F2 215 | #define D_NOREP 0x00007000 // Must not include F2 or F3 216 | #define D_MUSTREP 0x00008000 // Must include F3 (REP) 217 | #define D_MUSTREPE 0x00009000 // Must include F3 (REPE) 218 | #define D_MUSTREPNE 0x0000A000 // Must include F2 (REPNE) 219 | #define D_LOCKABLE 0x00010000 // Allows for F0 (LOCK, memory only) 220 | #define D_BHINT 0x00020000 // Allows for branch hints (2E, 3E) 221 | // Decoding of some commands with ModRM-SIB depends whether register or memory. 222 | #define D_MEMORY 0x00040000 // Mod field must indicate memory 223 | #define D_REGISTER 0x00080000 // Mod field must indicate register 224 | // Side effects caused by command. 225 | #define D_FLAGMASK 0x00700000 // Mask to extract modified flags 226 | #define D_NOFLAGS 0x00000000 // Flags S,Z,P,O,C remain unchanged 227 | #define D_ALLFLAGS 0x00100000 // Modifies flags S,Z,P,O,C 228 | #define D_FLAGZ 0x00200000 // Modifies flag Z only 229 | #define D_FLAGC 0x00300000 // Modifies flag C only 230 | #define D_FLAGSCO 0x00400000 // Modifies flag C and O only 231 | #define D_FLAGD 0x00500000 // Modifies flag D only 232 | #define D_FLAGSZPC 0x00600000 // Modifies flags Z, P and C only (FPU) 233 | #define D_NOCFLAG 0x00700000 // S,Z,P,O modified, C unaffected 234 | #define D_FPUMASK 0x01800000 // Mask for effects on FPU stack 235 | #define D_FPUSAME 0x00000000 // Doesn't rotate FPU stack (default) 236 | #define D_FPUPOP 0x00800000 // Pops FPU stack 237 | #define D_FPUPOP2 0x01000000 // Pops FPU stack twice 238 | #define D_FPUPUSH 0x01800000 // Pushes FPU stack 239 | #define D_CHGESP 0x02000000 // Command indirectly modifies ESP 240 | // Command features. 241 | #define D_HLADIR 0x04000000 // Nonstandard order of operands in HLA 242 | #define D_WILDCARD 0x08000000 // Mnemonics contains W/D wildcard ('*') 243 | #define D_COND 0x10000000 // Conditional (action depends on flags) 244 | #define D_USESCARRY 0x20000000 // Uses Carry flag 245 | #define D_USEMASK 0xC0000000 // Mask to detect unusual commands 246 | #define D_RARE 0x40000000 // Rare or obsolete in Win32 apps 247 | #define D_SUSPICIOUS 0x80000000 // Suspicious command 248 | #define D_UNDOC 0xC0000000 // Undocumented command 249 | 250 | // Extension of D_xxx. 251 | #define DX_ZEROMASK 0x00000003 // How to decode FLAGS.Z flag 252 | #define DX_JE 0x00000001 // JE, JNE instead of JZ, JNZ 253 | #define DX_JZ 0x00000002 // JZ, JNZ instead of JE, JNE 254 | #define DX_CARRYMASK 0x0000000C // How to decode FLAGS.C flag 255 | #define DX_JB 0x00000004 // JAE, JB instead of JC, JNC 256 | #define DX_JC 0x00000008 // JC, JNC instead of JAE, JB 257 | #define DX_RETN 0x00000010 // The mnemonics is RETN 258 | #define DX_VEX 0x00000100 // Requires VEX prefix 259 | #define DX_VLMASK 0x00000600 // Mask to extract VEX operand length 260 | #define DX_LSHORT 0x00000000 // 128-bit only 261 | #define DX_LBOTH 0x00000200 // Both 128- and 256-bit versions 262 | #define DX_LLONG 0x00000400 // 256-bit only 263 | #define DX_IGNOREL 0x00000600 // Ignore VEX.L 264 | #define DX_NOVREG 0x00000800 // VEX.vvvv must be set to all 1's 265 | #define DX_VWMASK 0x00003000 // Mask to extract VEX.W 266 | #define DX_W0 0x00001000 // VEX.W must be 0 267 | #define DX_W1 0x00002000 // VEX.W must be 1 268 | #define DX_LEADMASK 0x00070000 // Mask to extract leading opcode bytes 269 | #define DX_LEAD0F 0x00000000 // Implied 0F leading byte (default) 270 | #define DX_LEAD38 0x00010000 // Implied 0F 38 leading opcode bytes 271 | #define DX_LEAD3A 0x00020000 // Implied 0F 3A leading opcode bytes 272 | #define DX_WONKYTRAP 0x00800000 // Don't single-step this command 273 | #define DX_TYPEMASK 0xFF000000 // Precised command type mask 274 | #define DX_ADD 0x01000000 // The command is integer ADD 275 | #define DX_SUB 0x02000000 // The command is integer SUB 276 | #define DX_LEA 0x03000000 // The command is LEA 277 | #define DX_NOP 0x04000000 // The command is NOP 278 | 279 | //#define DX_LVEX (DX_VEX|DX_LBOTH) 280 | //#define DX_GVEX (DX_VEX|DX_LLONG) 281 | 282 | // Type of operand, only one is allowed. Size of SSE operands is given for the 283 | // case of 128-bit operations and usually doubles for 256-bit AVX commands. If 284 | // B_NOVEXSIZE is set, memory may double but XMM registers are not promoted to 285 | // YMM. 286 | #define B_ARGMASK 0x000000FF // Mask to extract type of argument 287 | #define B_NONE 0x00000000 // Operand absent 288 | #define B_AL 0x00000001 // Register AL 289 | #define B_AH 0x00000002 // Register AH 290 | #define B_AX 0x00000003 // Register AX 291 | #define B_CL 0x00000004 // Register CL 292 | #define B_CX 0x00000005 // Register CX 293 | #define B_DX 0x00000006 // Register DX 294 | #define B_DXPORT 0x00000007 // Register DX as I/O port address 295 | #define B_EAX 0x00000008 // Register EAX 296 | #define B_EBX 0x00000009 // Register EBX 297 | #define B_ECX 0x0000000A // Register ECX 298 | #define B_EDX 0x0000000B // Register EDX 299 | #define B_ACC 0x0000000C // Accumulator (AL/AX/EAX) 300 | #define B_STRCNT 0x0000000D // Register CX or ECX as REPxx counter 301 | #define B_DXEDX 0x0000000E // Register DX or EDX in DIV/MUL 302 | #define B_BPEBP 0x0000000F // Register BP or EBP in ENTER/LEAVE 303 | #define B_REG 0x00000010 // 8/16/32-bit register in Reg 304 | #define B_REG16 0x00000011 // 16-bit register in Reg 305 | #define B_REG32 0x00000012 // 32-bit register in Reg 306 | #define B_REGCMD 0x00000013 // 16/32-bit register in last cmd byte 307 | #define B_REGCMD8 0x00000014 // 8-bit register in last cmd byte 308 | #define B_ANYREG 0x00000015 // Reg field is unused, any allowed 309 | #define B_INT 0x00000016 // 8/16/32-bit register/memory in ModRM 310 | #define B_INT8 0x00000017 // 8-bit register/memory in ModRM 311 | #define B_INT16 0x00000018 // 16-bit register/memory in ModRM 312 | #define B_INT32 0x00000019 // 32-bit register/memory in ModRM 313 | #define B_INT1632 0x0000001A // 16/32-bit register/memory in ModRM 314 | #define B_INT64 0x0000001B // 64-bit integer in ModRM, memory only 315 | #define B_INT128 0x0000001C // 128-bit integer in ModRM, memory only 316 | #define B_IMMINT 0x0000001D // 8/16/32-bit int at immediate addr 317 | #define B_INTPAIR 0x0000001E // Two signed 16/32 in ModRM, memory only 318 | #define B_SEGOFFS 0x0000001F // 16:16/16:32 absolute address in memory 319 | #define B_STRDEST 0x00000020 // 8/16/32-bit string dest, [ES:(E)DI] 320 | #define B_STRDEST8 0x00000021 // 8-bit string destination, [ES:(E)DI] 321 | #define B_STRSRC 0x00000022 // 8/16/32-bit string source, [(E)SI] 322 | #define B_STRSRC8 0x00000023 // 8-bit string source, [(E)SI] 323 | #define B_XLATMEM 0x00000024 // 8-bit memory in XLAT, [(E)BX+AL] 324 | #define B_EAXMEM 0x00000025 // Reference to memory addressed by [EAX] 325 | #define B_LONGDATA 0x00000026 // Long data in ModRM, mem only 326 | #define B_ANYMEM 0x00000027 // Reference to memory, data unimportant 327 | #define B_STKTOP 0x00000028 // 16/32-bit int top of stack 328 | #define B_STKTOPFAR 0x00000029 // Top of stack (16:16/16:32 far addr) 329 | #define B_STKTOPEFL 0x0000002A // 16/32-bit flags on top of stack 330 | #define B_STKTOPA 0x0000002B // 16/32-bit top of stack all registers 331 | #define B_PUSH 0x0000002C // 16/32-bit int push to stack 332 | #define B_PUSHRET 0x0000002D // 16/32-bit push of return address 333 | #define B_PUSHRETF 0x0000002E // 16:16/16:32-bit push of far retaddr 334 | #define B_PUSHA 0x0000002F // 16/32-bit push all registers 335 | #define B_EBPMEM 0x00000030 // 16/32-bit int at [EBP] 336 | #define B_SEG 0x00000031 // Segment register in Reg 337 | #define B_SEGNOCS 0x00000032 // Segment register in Reg, but not CS 338 | #define B_SEGCS 0x00000033 // Segment register CS 339 | #define B_SEGDS 0x00000034 // Segment register DS 340 | #define B_SEGES 0x00000035 // Segment register ES 341 | #define B_SEGFS 0x00000036 // Segment register FS 342 | #define B_SEGGS 0x00000037 // Segment register GS 343 | #define B_SEGSS 0x00000038 // Segment register SS 344 | #define B_ST 0x00000039 // 80-bit FPU register in last cmd byte 345 | #define B_ST0 0x0000003A // 80-bit FPU register ST0 346 | #define B_ST1 0x0000003B // 80-bit FPU register ST1 347 | #define B_FLOAT32 0x0000003C // 32-bit float in ModRM, memory only 348 | #define B_FLOAT64 0x0000003D // 64-bit float in ModRM, memory only 349 | #define B_FLOAT80 0x0000003E // 80-bit float in ModRM, memory only 350 | #define B_BCD 0x0000003F // 80-bit BCD in ModRM, memory only 351 | #define B_MREG8x8 0x00000040 // MMX register as 8 8-bit integers 352 | #define B_MMX8x8 0x00000041 // MMX reg/memory as 8 8-bit integers 353 | #define B_MMX8x8DI 0x00000042 // MMX 8 8-bit integers at [DS:(E)DI] 354 | #define B_MREG16x4 0x00000043 // MMX register as 4 16-bit integers 355 | #define B_MMX16x4 0x00000044 // MMX reg/memory as 4 16-bit integers 356 | #define B_MREG32x2 0x00000045 // MMX register as 2 32-bit integers 357 | #define B_MMX32x2 0x00000046 // MMX reg/memory as 2 32-bit integers 358 | #define B_MREG64 0x00000047 // MMX register as 1 64-bit integer 359 | #define B_MMX64 0x00000048 // MMX reg/memory as 1 64-bit integer 360 | #define B_3DREG 0x00000049 // 3DNow! register as 2 32-bit floats 361 | #define B_3DNOW 0x0000004A // 3DNow! reg/memory as 2 32-bit floats 362 | #define B_XMM0I32x4 0x0000004B // XMM0 as 4 32-bit integers 363 | #define B_XMM0I64x2 0x0000004C // XMM0 as 2 64-bit integers 364 | #define B_XMM0I8x16 0x0000004D // XMM0 as 16 8-bit integers 365 | #define B_SREGF32x4 0x0000004E // SSE register as 4 32-bit floats 366 | #define B_SREGF32L 0x0000004F // Low 32-bit float in SSE register 367 | #define B_SREGF32x2L 0x00000050 // Low 2 32-bit floats in SSE register 368 | #define B_SSEF32x4 0x00000051 // SSE reg/memory as 4 32-bit floats 369 | #define B_SSEF32L 0x00000052 // Low 32-bit float in SSE reg/memory 370 | #define B_SSEF32x2L 0x00000053 // Low 2 32-bit floats in SSE reg/memory 371 | #define B_SREGF64x2 0x00000054 // SSE register as 2 64-bit floats 372 | #define B_SREGF64L 0x00000055 // Low 64-bit float in SSE register 373 | #define B_SSEF64x2 0x00000056 // SSE reg/memory as 2 64-bit floats 374 | #define B_SSEF64L 0x00000057 // Low 64-bit float in SSE reg/memory 375 | #define B_SREGI8x16 0x00000058 // SSE register as 16 8-bit sigints 376 | #define B_SSEI8x16 0x00000059 // SSE reg/memory as 16 8-bit sigints 377 | #define B_SSEI8x16DI 0x0000005A // SSE 16 8-bit sigints at [DS:(E)DI] 378 | #define B_SSEI8x8L 0x0000005B // Low 8 8-bit ints in SSE reg/memory 379 | #define B_SSEI8x4L 0x0000005C // Low 4 8-bit ints in SSE reg/memory 380 | #define B_SSEI8x2L 0x0000005D // Low 2 8-bit ints in SSE reg/memory 381 | #define B_SREGI16x8 0x0000005E // SSE register as 8 16-bit sigints 382 | #define B_SSEI16x8 0x0000005F // SSE reg/memory as 8 16-bit sigints 383 | #define B_SSEI16x4L 0x00000060 // Low 4 16-bit ints in SSE reg/memory 384 | #define B_SSEI16x2L 0x00000061 // Low 2 16-bit ints in SSE reg/memory 385 | #define B_SREGI32x4 0x00000062 // SSE register as 4 32-bit sigints 386 | #define B_SREGI32L 0x00000063 // Low 32-bit sigint in SSE register 387 | #define B_SREGI32x2L 0x00000064 // Low 2 32-bit sigints in SSE register 388 | #define B_SSEI32x4 0x00000065 // SSE reg/memory as 4 32-bit sigints 389 | #define B_SSEI32x2L 0x00000066 // Low 2 32-bit sigints in SSE reg/memory 390 | #define B_SREGI64x2 0x00000067 // SSE register as 2 64-bit sigints 391 | #define B_SSEI64x2 0x00000068 // SSE reg/memory as 2 64-bit sigints 392 | #define B_SREGI64L 0x00000069 // Low 64-bit sigint in SSE register 393 | #define B_EFL 0x0000006A // Flags register EFL 394 | #define B_FLAGS8 0x0000006B // Flags (low byte) 395 | #define B_OFFSET 0x0000006C // 16/32 const offset from next command 396 | #define B_BYTEOFFS 0x0000006D // 8-bit sxt const offset from next cmd 397 | #define B_FARCONST 0x0000006E // 16:16/16:32 absolute address constant 398 | #define B_DESCR 0x0000006F // 16:32 descriptor in ModRM 399 | #define B_1 0x00000070 // Immediate constant 1 400 | #define B_CONST8 0x00000071 // Immediate 8-bit constant 401 | #define B_CONST8_2 0x00000072 // Immediate 8-bit const, second in cmd 402 | #define B_CONST16 0x00000073 // Immediate 16-bit constant 403 | #define B_CONST 0x00000074 // Immediate 8/16/32-bit constant 404 | #define B_CONSTL 0x00000075 // Immediate 16/32-bit constant 405 | #define B_SXTCONST 0x00000076 // Immediate 8-bit sign-extended to size 406 | #define B_CR 0x00000077 // Control register in Reg 407 | #define B_CR0 0x00000078 // Control register CR0 408 | #define B_DR 0x00000079 // Debug register in Reg 409 | #define B_FST 0x0000007A // FPU status register 410 | #define B_FCW 0x0000007B // FPU control register 411 | #define B_MXCSR 0x0000007C // SSE media control and status register 412 | #define B_SVEXF32x4 0x0000007D // SSE reg in VEX as 4 32-bit floats 413 | #define B_SVEXF32L 0x0000007E // Low 32-bit float in SSE in VEX 414 | #define B_SVEXF64x2 0x0000007F // SSE reg in VEX as 2 64-bit floats 415 | #define B_SVEXF64L 0x00000080 // Low 64-bit float in SSE in VEX 416 | #define B_SVEXI8x16 0x00000081 // SSE reg in VEX as 16 8-bit sigints 417 | #define B_SVEXI16x8 0x00000082 // SSE reg in VEX as 8 16-bit sigints 418 | #define B_SVEXI32x4 0x00000083 // SSE reg in VEX as 4 32-bit sigints 419 | #define B_SVEXI64x2 0x00000084 // SSE reg in VEX as 2 64-bit sigints 420 | #define B_SIMMI8x16 0x00000085 // SSE reg in immediate 8-bit constant 421 | // Type modifiers, used for interpretation of contents, only one is allowed. 422 | #define B_MODMASK 0x000F0000 // Mask to extract type modifier 423 | #define B_NONSPEC 0x00000000 // Non-specific operand 424 | #define B_UNSIGNED 0x00010000 // Decode as unsigned decimal 425 | #define B_SIGNED 0x00020000 // Decode as signed decimal 426 | #define B_BINARY 0x00030000 // Decode as binary (full hex) data 427 | #define B_BITCNT 0x00040000 // Bit count 428 | #define B_SHIFTCNT 0x00050000 // Shift count 429 | #define B_COUNT 0x00060000 // General-purpose count 430 | #define B_NOADDR 0x00070000 // Not an address 431 | #define B_JMPCALL 0x00080000 // Near jump/call/return destination 432 | #define B_JMPCALLFAR 0x00090000 // Far jump/call/return destination 433 | #define B_STACKINC 0x000A0000 // Unsigned stack increment/decrement 434 | #define B_PORT 0x000B0000 // I/O port 435 | #define B_ADDR 0x000F0000 // Used internally 436 | // Validity markers. 437 | #define B_MEMORY 0x00100000 // Memory only, reg version different 438 | #define B_REGISTER 0x00200000 // Register only, mem version different 439 | #define B_MEMONLY 0x00400000 // Warn if operand in register 440 | #define B_REGONLY 0x00800000 // Warn if operand in memory 441 | #define B_32BITONLY 0x01000000 // Warn if 16-bit operand 442 | #define B_NOESP 0x02000000 // ESP is not allowed 443 | // Miscellaneous options. 444 | #define B_NOVEXSIZE 0x04000000 // Always 128-bit SSE in 256-bit AVX 445 | #define B_SHOWSIZE 0x08000000 // Always show argument size in disasm 446 | #define B_CHG 0x10000000 // Changed, old contents is not used 447 | #define B_UPD 0x20000000 // Modified using old contents 448 | #define B_PSEUDO 0x40000000 // Pseoudooperand, not in assembler cmd 449 | #define B_NOSEG 0x80000000 // Don't add offset of selector 450 | 451 | // Location of operand, only one bit is allowed. 452 | #define OP_SOMEREG 0x000000FF // Mask for any kind of register 453 | #define OP_REGISTER 0x00000001 // Operand is a general-purpose register 454 | #define OP_SEGREG 0x00000002 // Operand is a segment register 455 | #define OP_FPUREG 0x00000004 // Operand is a FPU register 456 | #define OP_MMXREG 0x00000008 // Operand is a MMX register 457 | #define OP_3DNOWREG 0x00000010 // Operand is a 3DNow! register 458 | #define OP_SSEREG 0x00000020 // Operand is a SSE register 459 | #define OP_CREG 0x00000040 // Operand is a control register 460 | #define OP_DREG 0x00000080 // Operand is a debug register 461 | #define OP_MEMORY 0x00000100 // Operand is in memory 462 | #define OP_CONST 0x00000200 // Operand is an immediate constant 463 | // Additional operand properties. 464 | #define OP_PORT 0x00000400 // Used to access I/O port 465 | #define OP_OTHERREG 0x00000800 // Special register like EFL or MXCSR 466 | #define OP_INVALID 0x00001000 // Invalid operand, like reg in mem-only 467 | #define OP_PSEUDO 0x00002000 // Pseudooperand (not in mnenonics) 468 | #define OP_MOD 0x00004000 // Command may change/update operand 469 | #define OP_MODREG 0x00008000 // Memory, but modifies reg (POP,MOVSD) 470 | #define OP_IMPORT 0x00020000 // Value imported from different module 471 | #define OP_SELECTOR 0x00040000 // Includes immediate selector 472 | // Additional properties of memory address. 473 | #define OP_INDEXED 0x00080000 // Memory address contains registers 474 | #define OP_OPCONST 0x00100000 // Memory address contains constant 475 | #define OP_ADDR16 0x00200000 // 16-bit memory address 476 | #define OP_ADDR32 0x00400000 // Explicit 32-bit memory address 477 | 478 | #define DAMODE_MASM 0 // MASM assembling/disassembling style 479 | #define DAMODE_IDEAL 1 // IDEAL assembling/disassembling style 480 | #define DAMODE_HLA 2 // HLA assembling/disassembling style 481 | #define DAMODE_ATT 3 // AT&T disassembling style 482 | 483 | #define NUM_STYLE 0x0003 // Mask to extract hex style 484 | #define NUM_STD 0x0000 // 123, 12345678h, 0ABCD1234h 485 | #define NUM_X 0x0001 // 123, 0x12345678, 0xABCD1234 486 | #define NUM_OLLY 0x0002 // 123., 12345678, 0ABCD1234 487 | #define NUM_LONG 0x0010 // 00001234h instead of 1234h 488 | #define NUM_DECIMAL 0x0020 // 123 instead of 7Bh if under DECLIMIT 489 | 490 | // Disassembling options. 491 | #define DA_TEXT 0x00000001 // Decode command to text and comment 492 | #define DA_HILITE 0x00000002 // Use syntax highlighting 493 | #define DA_JZ 0x00000004 // JZ, JNZ instead of JE, JNE 494 | #define DA_JC 0x00000008 // JC, JNC instead of JAE, JB 495 | #define DA_DUMP 0x00000020 // Dump command to hexadecimal text 496 | #define DA_PSEUDO 0x00000400 // List pseudooperands 497 | 498 | // Disassembling errors. 499 | #define DAE_NOERR 0x00000000 // No errors 500 | #define DAE_BADCMD 0x00000001 // Unrecognized command 501 | #define DAE_CROSS 0x00000002 // Command crosses end of memory block 502 | #define DAE_MEMORY 0x00000004 // Register where only memory allowed 503 | #define DAE_REGISTER 0x00000008 // Memory where only register allowed 504 | #define DAE_LOCK 0x00000010 // LOCK prefix is not allowed 505 | #define DAE_BADSEG 0x00000020 // Invalid segment register 506 | #define DAE_SAMEPREF 0x00000040 // Two prefixes from the same group 507 | #define DAE_MANYPREF 0x00000080 // More than 4 prefixes 508 | #define DAE_BADCR 0x00000100 // Invalid CR register 509 | #define DAE_INTERN 0x00000200 // Internal error 510 | 511 | // Disassembling warnings. 512 | #define DAW_NOWARN 0x00000000 // No warnings 513 | #define DAW_DATASIZE 0x00000001 // Superfluous data size prefix 514 | #define DAW_ADDRSIZE 0x00000002 // Superfluous address size prefix 515 | #define DAW_SEGPREFIX 0x00000004 // Superfluous segment override prefix 516 | #define DAW_REPPREFIX 0x00000008 // Superfluous REPxx prefix 517 | #define DAW_DEFSEG 0x00000010 // Segment prefix coincides with default 518 | #define DAW_JMP16 0x00000020 // 16-bit jump, call or return 519 | #define DAW_FARADDR 0x00000040 // Far jump or call 520 | #define DAW_SEGMOD 0x00000080 // Modifies segment register 521 | #define DAW_PRIV 0x00000100 // Privileged command 522 | #define DAW_IO 0x00000200 // I/O command 523 | #define DAW_SHIFT 0x00000400 // Shift out of range 1..31 524 | #define DAW_LOCK 0x00000800 // Command with valid LOCK prefix 525 | #define DAW_STACK 0x00001000 // Unaligned stack operation 526 | #define DAW_NOESP 0x00002000 // Suspicious use of stack pointer 527 | #define DAW_RARE 0x00004000 // Rare, seldom used command 528 | #define DAW_NONCLASS 0x00008000 // Non-standard or non-documented code 529 | #define DAW_INTERRUPT 0x00010000 // Interrupt command 530 | 531 | // List of prefixes. 532 | #define PF_SEGMASK 0x0000003F // Mask for segment override prefixes 533 | #define PF_ES 0x00000001 // 0x26, ES segment override 534 | #define PF_CS 0x00000002 // 0x2E, CS segment override 535 | #define PF_SS 0x00000004 // 0x36, SS segment override 536 | #define PF_DS 0x00000008 // 0x3E, DS segment override 537 | #define PF_FS 0x00000010 // 0x64, FS segment override 538 | #define PF_GS 0x00000020 // 0x65, GS segment override 539 | #define PF_DSIZE 0x00000040 // 0x66, data size override 540 | #define PF_ASIZE 0x00000080 // 0x67, address size override 541 | #define PF_LOCK 0x00000100 // 0xF0, bus lock 542 | #define PF_REPMASK 0x00000600 // Mask for repeat prefixes 543 | #define PF_REPNE 0x00000200 // 0xF2, REPNE prefix 544 | #define PF_REP 0x00000400 // 0xF3, REP/REPE prefix 545 | #define PF_BYTE 0x00000800 // Size bit in command, used in cmdexec 546 | #define PF_MUSTMASK D_MUSTMASK // Necessary prefixes, used in t_asmmod 547 | #define PF_VEX2 0x00010000 // 2-byte VEX prefix 548 | #define PF_VEX3 0x00020000 // 3-byte VEX prefix 549 | // Useful shortcuts. 550 | #define PF_66 PF_DSIZE // Alternative names for SSE prefixes 551 | #define PF_F2 PF_REPNE 552 | #define PF_F3 PF_REP 553 | #define PF_HINT (PF_CS|PF_DS) // Alternative names for branch hints 554 | #define PF_NOTTAKEN PF_CS 555 | #define PF_TAKEN PF_DS 556 | #define PF_VEX (PF_VEX2|PF_VEX3) 557 | 558 | typedef struct t_modrm { // ModRM byte decoding 559 | ulong size; // Total size with SIB and disp, bytes 560 | struct t_modrm *psib; // Pointer to SIB table or NULL 561 | ulong dispsize; // Size of displacement or 0 if none 562 | ulong features; // Operand features, set of OP_xxx 563 | int reg; // Register index or REG_UNDEF 564 | int defseg; // Default selector (SEG_xxx) 565 | uchar scale[NREG]; // Scales of registers in memory address 566 | ulong aregs; // List of registers used in address 567 | int basereg; // Register used as base or REG_UNDEF 568 | tchar ardec[SHORTNAME]; // Register part of address, INTEL fmt 569 | tchar aratt[SHORTNAME]; // Register part of address, AT&T fmt 570 | } t_modrm; 571 | 572 | typedef struct t_bincmd { // Description of 80x86 command 573 | tchar *name; // Symbolic name for this command 574 | ulong cmdtype; // Command's features, set of D_xxx 575 | ulong exttype; // More features, set of DX_xxx 576 | ulong length; // Length of main code (before ModRM/SIB) 577 | ulong mask; // Mask for first 4 bytes of the command 578 | ulong code; // Compare masked bytes with this 579 | ulong postbyte; // Postbyte 580 | ulong arg[NOPERAND]; // Types of arguments, set of B_xxx 581 | } t_bincmd; 582 | 583 | typedef struct t_chain { // Element of command chain 584 | const t_bincmd *pcmd; // Pointer to command descriptor or NULL 585 | struct t_chain *pnext; // Pointer to next element in chain 586 | } t_chain; 587 | 588 | typedef struct t_config { // Disassembler configuration 589 | int disasmmode; // Main style, one of DAMODE_xxx 590 | int memmode; // Constant part of address, NUM_xxx 591 | int jmpmode; // Jump/call destination, NUM_xxx 592 | int binconstmode; // Binary constants, NUM_xxx 593 | int constmode; // Numeric constants, NUM_xxx 594 | int lowercase; // Force lowercase display 595 | int tabarguments; // Tab between mnemonic and arguments 596 | int extraspace; // Extra space between arguments 597 | int useretform; // Use RET instead of RETN 598 | int shortstringcmds; // Use short form of string commands 599 | int putdefseg; // Display default segments in listing 600 | int showmemsize; // Always show memory size 601 | int shownear; // Show NEAR modifiers 602 | int ssesizemode; // How to decode size of SSE operands 603 | int jumphintmode; // How to decode jump hints 604 | int sizesens; // How to decode size-sensitive mnemonics 605 | int simplifiedst; // How to decode top of FPU stack 606 | int hiliteoperands; // Highlight operands 607 | } t_config; 608 | 609 | typedef struct t_operand { // Description of disassembled operand 610 | // Description of operand. 611 | ulong features; // Operand features, set of OP_xxx 612 | ulong arg; // Operand type, set of B_xxx 613 | // int optype; // DEC_INT, DEC_FLOAT or DEC_UNKNOWN 614 | int opsize; // Total size of data, bytes 615 | int granularity; // Size of element (opsize exc. MMX/SSE) 616 | int reg; // REG_xxx (also ESP in POP) or REG_UNDEF 617 | ulong uses; // List of used regs (not in address!) 618 | ulong modifies; // List of modified regs (not in addr!) 619 | // Description of memory address. 620 | int seg; // Selector (SEG_xxx) 621 | uchar scale[NREG]; // Scales of registers in memory address 622 | ulong aregs; // List of registers used in address 623 | ulong opconst; // Constant or const part of address 624 | ulong selector; // Immediate selector in far jump/call 625 | // Textual decoding. 626 | tchar text[TEXTLEN]; // Operand, decoded to text 627 | } t_operand; 628 | 629 | // Note that used registers are those which contents is necessary to create 630 | // result. Modified registers are those which value is changed. For example, 631 | // command MOV EAX,[EBX+ECX] uses EBX and ECX and modifies EAX. Command 632 | // ADD ESI,EDI uses ESI and EDI and modifies ESI. 633 | typedef struct t_disasm { // Disassembled command 634 | ulong ip; // Address of first command byte 635 | ulong size; // Full length of command, bytes 636 | ulong cmdtype; // Type of command, D_xxx 637 | ulong exttype; // More features, set of DX_xxx 638 | ulong prefixes; // List of prefixes, set of PF_xxx 639 | ulong nprefix; // Number of prefixes, including SSE2 640 | ulong memfixup; // Offset of first 4-byte fixup or -1 641 | ulong immfixup; // Offset of second 4-byte fixup or -1 642 | int errors; // Set of DAE_xxx 643 | int warnings; // Set of DAW_xxx 644 | ulong uses; // List of used registers 645 | ulong modifies; // List of modified registers 646 | ulong memconst; // Constant in memory address or 0 647 | ulong stackinc; // Data size in ENTER/RETN/RETF 648 | t_operand op[NOPERAND]; // Operands 649 | tchar dump[TEXTLEN]; // Hex dump of the command 650 | tchar result[TEXTLEN]; // Fully decoded command as text 651 | uchar mask[TEXTLEN]; // Mask to highlight result 652 | int masksize; // Length of mask corresponding to result 653 | } t_disasm; 654 | 655 | extern t_modrm modrm16[256]; // 16-bit ModRM decodings 656 | extern t_modrm modrm32[256]; // 32-bit ModRM decodings without SIB 657 | extern t_modrm sib0[256]; // ModRM-SIB decodings with Mod=00 658 | extern t_modrm sib1[256]; // ModRM-SIB decodings with Mod=01 659 | extern t_modrm sib2[256]; // ModRM-SIB decodings with Mod=10 660 | 661 | extern const t_bincmd bincmd[]; // List of 80x86 commands 662 | extern t_chain *cmdchain; // Commands sorted by first CMDMASK bits 663 | 664 | int Preparedisasm(void); 665 | void Finishdisasm(void); 666 | 667 | ulong Disasm(uchar *cmd,ulong cmdsize,ulong cmdip, 668 | t_disasm *da,int cmdmode,t_config *cmdconfig, 669 | int (*decodeaddress)(tchar *s,ulong addr)); 670 | tchar *Geterrwarnmessage(ulong errors,ulong warnings); 671 | 672 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // Free Disassembler and Assembler -- Demo program 2 | // 3 | // Copyright (C) 2001 Oleh Yuschuk 4 | // 5 | // This program is free software; you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation; either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | #define STRICT 21 | #define MAINPROG // Place all unique variables here 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #pragma hdrstop 30 | 31 | 32 | #include "disasm.h" 33 | 34 | void main(void) { // Old form. So what? 35 | int i,j,n; 36 | ulong l; 37 | char *pasm; 38 | t_disasm da; 39 | t_asmmodel am; 40 | char s[TEXTLEN],errtext[TEXTLEN]; 41 | 42 | // Demonstration of Disassembler. 43 | printf("Disassembler:\n"); 44 | 45 | // Quickly determine size of command. 46 | l=Disasm("\x81\x05\xE0\x5A\x47\x00\x01\x00\x00\x00\x11\x22\x33\x44\x55\x66", 47 | 10,0x400000,&da,DISASM_SIZE); 48 | printf("Size of command = %i bytes\n",l); 49 | 50 | // ADD [475AE0],1 MASM mode, lowercase, don't show default segment 51 | ideal=0; lowercase=1; putdefseg=1; 52 | l=Disasm("\x33\x44\x55\x66", 53 | 6,0x400000,&da,DISASM_CODE); 54 | printf("%3i %-24s %-24s (MASM)\n",l,da.dump,da.result); 55 | 56 | // ADD [475AE0],1 IDEAL mode, uppercase, show default segment 57 | ideal=1; lowercase=0; putdefseg=1; 58 | l=Disasm("\x81\x05\xE0\x5A\x47\x00\x01\x00\x00\x00", 59 | 10,0x400000,&da,DISASM_CODE); 60 | printf("%3i %-24s %-24s (IDEAL)\n",l,da.dump,da.result); 61 | 62 | // CALL 45187C 63 | l=Disasm("\xE8\x1F\x14\x00\x00", 64 | 5,0x450458,&da,DISASM_CODE); 65 | printf("%3i %-24s %-24s jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst); 66 | 67 | // JNZ 450517 68 | l=Disasm("\x75\x72", 69 | 2,0x4504A3,&da,DISASM_CODE); 70 | printf("%3i %-24s %-24s jmpconst=%08X\n",l,da.dump,da.result,da.jmpconst); 71 | 72 | // Demonstration of Assembler. 73 | printf("\nAssembler:\n"); 74 | 75 | // Assemble one of the commands above. First try form with 32-bit immediate. 76 | pasm="ADD [DWORD 475AE0],1"; 77 | printf("%s:\n",pasm); 78 | j=Assemble(pasm,0x400000,&am,0,0,errtext); 79 | n=sprintf_s(s,"%3i ",j); 80 | for (i=0; i