├── LICENSE ├── assets └── pic1.png ├── public ├── Description │ ├── File │ │ ├── CloseHandle.py │ │ ├── CreateFileA.py │ │ ├── OpenFile.py │ │ ├── ReadFile.py │ │ ├── WriteFile.py │ │ └── _lclose.py │ ├── FileDescription.py │ ├── Heap │ │ ├── HeapAlloc.py │ │ ├── HeapCreate.py │ │ ├── HeapDestroy.py │ │ └── HeapFree.py │ ├── HeapDescription.py │ ├── HookFunc │ │ ├── StartTrace.py │ │ └── StopTrace.py │ ├── HookFuncDescription.py │ ├── MessageBox │ │ └── MessageBoxA.py │ ├── MessageBoxDescription.py │ ├── Regedit │ │ ├── RegCloseKey.py │ │ ├── RegCreateKeyExA.py │ │ ├── RegOpenKeyExA.py │ │ ├── RegQueryValueExA.py │ │ └── RegSetValueExA.py │ ├── RegeditDescription.py │ ├── Socket │ │ ├── WSACleanup.py │ │ ├── WSAStartup.py │ │ ├── closesocket.py │ │ ├── connect.py │ │ ├── recv.py │ │ ├── send.py │ │ └── socket.py │ └── SocketDescription.py ├── Handlers │ ├── FileHandler.py │ ├── HeapHandler.py │ ├── HookFuncHandler.py │ ├── MessageBoxHandler.py │ ├── RegHandler.py │ └── SocketHandler.py ├── handleMain.py ├── main.py ├── pipeThread.py ├── requirements.txt ├── template │ └── index.html └── utils.py ├── readme.md ├── src ├── DetoursDll3 │ ├── DetoursDll3.sln │ ├── DetoursDll3.vcxproj │ ├── DetoursDll3.vcxproj.filters │ ├── base64.h │ ├── dllmain.cpp │ ├── framework.h │ ├── pch.cpp │ └── pch.h ├── Injector │ ├── Injector.cpp │ ├── Injector.h │ ├── Injector.sln │ ├── Injector.vcxproj │ └── Injector.vcxproj.filters └── web │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .postcssrc.js │ ├── .vscode │ ├── extensions.json │ └── settings.json │ ├── README.md │ ├── babel.config.js │ ├── jsconfig.json │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.ico │ └── icons │ │ ├── favicon-128x128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ └── favicon-96x96.png │ ├── quasar │ ├── quasar.conf.js │ ├── src-electron │ ├── electron-main.js │ ├── electron-preload.js │ └── icons │ │ ├── icon.icns │ │ ├── icon.ico │ │ └── linux-512x512.png │ └── src │ ├── App.vue │ ├── assets │ └── quasar-logo-vertical.svg │ ├── boot │ ├── .gitkeep │ ├── axios.js │ └── socketio.js │ ├── components │ └── EssentialLink.vue │ ├── css │ ├── app.scss │ └── quasar.variables.scss │ ├── index.template.html │ ├── layouts │ └── MainLayout.vue │ ├── pages │ ├── Error404.vue │ ├── Index.vue │ └── descriptionGenerator.js │ └── router │ ├── index.js │ └── routes.js └── test ├── HeapFreeTwice ├── .idea │ ├── HeapFreeTwice.iml │ ├── modules.xml │ ├── vcs.xml │ └── workspace.xml ├── Target5.cpp ├── Target5.sln ├── Target5.vcxproj └── Target5.vcxproj.filters └── MFCTest ├── Target4.cpp ├── Target4.h ├── Target4.rc ├── Target4.sln ├── Target4.vcxproj ├── Target4.vcxproj.filters ├── Target4Dlg.cpp ├── Target4Dlg.h ├── framework.h ├── pch.cpp ├── pch.h ├── res ├── Target4.ico └── Target4.rc2 ├── resource.h ├── targetver.h └── test.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 6QHTSK 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/assets/pic1.png -------------------------------------------------------------------------------- /public/Description/File/CloseHandle.py: -------------------------------------------------------------------------------- 1 | from utils import convertResult, to32Hex, formatErrorCode 2 | from os.path import basename 3 | 4 | 5 | def description(event): 6 | info = event["event"] 7 | event["eventDescription"] = { 8 | "hObject": { 9 | "description": "要关闭的文件句柄", 10 | "value": [to32Hex(info["hFile"]), info["path"]] 11 | }, 12 | "return": { 13 | "description": "执行结果", 14 | "value": convertResult(info["return"]) 15 | } 16 | } 17 | if "errorCode" in info: 18 | event["eventDescription"].update({ 19 | "errorCode": { 20 | "description": "错误代码", 21 | "value": formatErrorCode(info["errorCode"]) 22 | } 23 | }) 24 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle" 25 | event["description"] = "关闭文件{}".format(basename(info["path"])) 26 | -------------------------------------------------------------------------------- /public/Description/File/CreateFileA.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, convertOr, convertDict, to32Hex, formatErrorCode 2 | from os.path import basename 3 | 4 | 5 | def description(event): 6 | info = event["event"] 7 | event["eventDescription"] = { 8 | "lpFileName": { 9 | "description": "创建或打开的文件或设备的名称", 10 | "value": info["lpFileName"] 11 | }, 12 | "dwDesiredAccess": { 13 | "description": "申请访问权限", 14 | "value": convertOr(info["dwDesiredAccess"], convertDict["FileAccessMask"]) 15 | }, 16 | "dwShareMode": { 17 | "description": "共享模式", 18 | "value": convertOr(info["dwShareMode"], convertDict["FileShareMode"]) 19 | }, 20 | "lpSecurityAttributes": { 21 | "description": "安全参数结构指针", 22 | "value": to32Hex(info["lpSecurityAttributes"], "NULL") 23 | }, 24 | "dwCreationDisposition": { 25 | "description": "文件打开方式", 26 | "value": convertEqual(info["dwCreationDisposition"], convertDict["FileCreationDisposition"]) 27 | }, 28 | "dwFlagsAndAttributes": { 29 | "description": "设置文件参数", 30 | "value": convertOr(info["dwFlagsAndAttributes"], convertDict["FileFlagsAndAttributes"]) 31 | }, 32 | "hTemplate": { 33 | "description": "模板文件句柄", 34 | "value": to32Hex(info["hTemplateFile"], "NULL") 35 | }, 36 | "return": { 37 | "description": "文件句柄", 38 | "value": to32Hex(info["handle"], "NULL") 39 | } 40 | } 41 | if "errorCode" in info: 42 | event["eventDescription"].update({ 43 | "errorCode": { 44 | "description": "错误代码", 45 | "value": formatErrorCode(info["errorCode"]) 46 | } 47 | }) 48 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea" 49 | event["description"] = "打开了文件{}".format( 50 | basename(event["eventDescription"]["lpFileName"]["value"])) 51 | -------------------------------------------------------------------------------- /public/Description/File/OpenFile.py: -------------------------------------------------------------------------------- 1 | from utils import to32Hex, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "lpFileName": { 8 | "description": "文件名", 9 | "value": info["lpFileName"] 10 | }, 11 | "lpReOpenBuff": { 12 | "description": "参数结构体指针", 13 | "value": to32Hex(info["lpReOpenBuff"]) 14 | }, 15 | "uStyle": { 16 | "description": "操作代码", 17 | "value": to32Hex(info["uStyle"]) 18 | }, 19 | "return": { 20 | "description": "操作句柄", 21 | "value": to32Hex(info["hFile"]) 22 | } 23 | } 24 | if "errorCode" in info: 25 | event["eventDescription"].update({ 26 | "errorCode": { 27 | "description": "错误代码", 28 | "value": formatErrorCode(info["errorCode"]) 29 | } 30 | }) 31 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfile" 32 | event["description"] = "[过时的函数] 打开了{}文件".format( 33 | event["eventDescription"]["lpFileName"]["value"] 34 | ) 35 | -------------------------------------------------------------------------------- /public/Description/File/ReadFile.py: -------------------------------------------------------------------------------- 1 | from utils import convertResult, to32Hex, toMemorySize, formatErrorCode 2 | from os.path import basename 3 | 4 | 5 | def description(event): 6 | info = event["event"] 7 | event["eventDescription"] = { 8 | "hFile": { 9 | "description": "文件句柄", 10 | "value": [to32Hex(info["hFile"]), info["path"]] 11 | }, 12 | "lpBuffer": { 13 | "description": "Buffer地址", 14 | "value": to32Hex(info["lpBuffer"]), 15 | "buffer": info.get("lpBufferValue", "") 16 | }, 17 | "nNumberOfBytesToRead": { 18 | "description": "最大读取字节数", 19 | "value": toMemorySize(info["nNumberOfBytesToRead"]) 20 | }, 21 | "lpNumberOfBytesRead": { 22 | "description": "读取字节数的指针", 23 | "value": to32Hex(info["lpNumberOfBytesRead"], "NULL") 24 | }, 25 | "lpOverlapped": { 26 | "description": "指向OVERLAPPED参数的指针", 27 | "value": to32Hex(info["lpOverlapped"], "NULL") 28 | }, 29 | "return": { 30 | "description": "执行结果", 31 | "value": convertResult(info['return']) 32 | } 33 | } 34 | if "errorCode" in info: 35 | event["eventDescription"].update({ 36 | "errorCode": { 37 | "description": "错误代码", 38 | "value": formatErrorCode(info["errorCode"]) 39 | } 40 | }) 41 | if info["lpNumberOfBytesRead"] != 0: 42 | event["eventDescription"]["lpNumberOfBytesRead"] = { 43 | "description": "读取字节数", 44 | "value": toMemorySize(info["lpNumberOfBytesReadValue"]) 45 | } 46 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile" 47 | event["description"] = "读取文件{}内容".format(basename(info["path"])) 48 | -------------------------------------------------------------------------------- /public/Description/File/WriteFile.py: -------------------------------------------------------------------------------- 1 | from utils import to32Hex, toMemorySize, convertResult, formatErrorCode 2 | from os.path import basename 3 | 4 | 5 | def description(event): 6 | info = event["event"] 7 | event["eventDescription"] = { 8 | "hFile": { 9 | "description": "文件句柄", 10 | "value": [to32Hex(info["hFile"]), info["path"]] 11 | }, 12 | "lpBuffer": { 13 | "description": "Buffer地址", 14 | "value": to32Hex(info["lpBuffer"]), 15 | "buffer": info.get("lpBufferValue", "") 16 | }, 17 | "nNumberOfBytesToWrite": { 18 | "description": "最大写字节数", 19 | "value": toMemorySize(info["nNumberOfBytesToWrite"]) 20 | }, 21 | "lpNumberOfBytesWritten": { 22 | "description": "写字节数的指针", 23 | "value": to32Hex(info["lpNumberOfBytesWritten"], "NULL") 24 | }, 25 | "lpOverlapped": { 26 | "description": "指向OVERLAPPED参数的指针", 27 | "value": to32Hex(info["lpOverlapped"], "NULL") 28 | }, 29 | "return": { 30 | "description": "执行结果", 31 | "value": convertResult(info['return']) 32 | } 33 | } 34 | if "errorCode" in info: 35 | event["eventDescription"].update({ 36 | "errorCode": { 37 | "description": "错误代码", 38 | "value": formatErrorCode(info["errorCode"]) 39 | } 40 | }) 41 | if info["lpNumberOfBytesWritten"] != 0: 42 | event["eventDescription"]["lpNumberOfBytesWritten"] = { 43 | "description": "写字节数", 44 | "value": toMemorySize(info["lpNumberOfBytesWrittenValue"]) 45 | } 46 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile" 47 | event["description"] = "写文件{}内容".format(basename(info["path"])) 48 | -------------------------------------------------------------------------------- /public/Description/File/_lclose.py: -------------------------------------------------------------------------------- 1 | from utils import to32Hex 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hFile": { 8 | "description": "操作句柄", 9 | "value": to32Hex(info["hHeap"], "NULL") 10 | }, 11 | "return": { 12 | "description": "文件关闭句柄", 13 | "value": to32Hex(info["return"], "NULL") 14 | } 15 | } 16 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-_lclose" 17 | event["description"] = "[过时的函数] 关闭文件句柄" 18 | -------------------------------------------------------------------------------- /public/Description/FileDescription.py: -------------------------------------------------------------------------------- 1 | from Description.File.CreateFileA import description as createFile 2 | from Description.File.OpenFile import description as openFile 3 | from Description.File.ReadFile import description as readFile 4 | from Description.File.WriteFile import description as writeFile 5 | from Description.File._lclose import description as _lclose 6 | from Description.File.CloseHandle import description as closeHandle 7 | 8 | 9 | def FileDescription(event): 10 | info = event["event"] 11 | operation = info["Operation"] 12 | print(operation) 13 | if operation == "CreateFileA": 14 | createFile(event) 15 | elif operation == "OpenFile": 16 | openFile(event) 17 | elif operation == "ReadFile": 18 | readFile(event) 19 | elif operation == "WriteFile": 20 | writeFile(event) 21 | elif operation == "_lclose": 22 | _lclose(event) 23 | elif operation == "CloseHandle": 24 | closeHandle(event) 25 | -------------------------------------------------------------------------------- /public/Description/Heap/HeapAlloc.py: -------------------------------------------------------------------------------- 1 | from utils import convertOr, toMemorySize, to32Hex, convertDict 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hHeap": { 8 | "description": "操作堆的句柄", 9 | "value": to32Hex(info["hHeap"], "NULL") 10 | }, 11 | "dwFlags": { 12 | "description": "申请选项", 13 | "value": convertOr(info["dwFlags"], convertDict["HeapOptions"]) 14 | }, 15 | "dwBytes": { 16 | "description": "要分配的字节数", 17 | "value": toMemorySize(info["dwBytes"]) 18 | }, 19 | "return": { 20 | "description": "分配内存块的指针", 21 | "value": to32Hex(info["address"], "分配失败") 22 | } 23 | } 24 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc" 25 | event["description"] = "在堆[{}]上申请了{}大小的内存区域".format( 26 | event["eventDescription"]["hHeap"]["value"], 27 | event["eventDescription"]["dwBytes"]["value"] 28 | ) 29 | -------------------------------------------------------------------------------- /public/Description/Heap/HeapCreate.py: -------------------------------------------------------------------------------- 1 | from utils import convertOr, toMemorySize, to32Hex, convertDict, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "fIOptions": { 8 | "descrioption": "创建选项", 9 | "value": convertOr(info["fIOptions"], convertDict["HeapOptions"]), 10 | }, 11 | "dwInitialSize": { 12 | "description": "堆的初始大小", 13 | "value": toMemorySize(info["dwInitialSize"], "宿主机内存一页分页"), 14 | }, 15 | "dwMaximumSize": { 16 | "description": "堆的最大大小", 17 | "value": toMemorySize(info["dwMaximumSize"], "无限制") 18 | }, 19 | "return": { 20 | "description": "创建堆的句柄", 21 | "value": to32Hex(info["hHeap"], '创建堆失败') 22 | } 23 | } 24 | if "errorCode" in info: 25 | event["eventDescription"].update({ 26 | "errorCode": { 27 | "description": "错误代码", 28 | "value": formatErrorCode(info["errorCode"]) 29 | } 30 | }) 31 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapcreate" 32 | event["description"] = "创建了一个初始大小为{},最大大小为{}的堆[{}]。".format( 33 | event["eventDescription"]["dwInitialSize"]["value"], 34 | event["eventDescription"]["dwMaximumSize"]["value"], 35 | event["eventDescription"]["return"]["value"]) 36 | -------------------------------------------------------------------------------- /public/Description/Heap/HeapDestroy.py: -------------------------------------------------------------------------------- 1 | from utils import convertResult, to32Hex, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hHeap": { 8 | "description": "要摧毁的堆的句柄", 9 | "value": to32Hex(info["hHeap"], "NULL") 10 | }, 11 | "return": { 12 | "description": "摧毁结果", 13 | "value": convertResult(info["return"]) 14 | } 15 | } 16 | if "errorCode" in info: 17 | event["eventDescription"].update({ 18 | "errorCode": { 19 | "description": "错误代码", 20 | "value": formatErrorCode(info["errorCode"]) 21 | } 22 | }) 23 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapdestroy" 24 | event["description"] = "{}地摧毁了堆[{}]".format( 25 | event["eventDescription"]["return"]["value"], 26 | event["eventDescription"]["hHeap"]["value"] 27 | ) 28 | -------------------------------------------------------------------------------- /public/Description/Heap/HeapFree.py: -------------------------------------------------------------------------------- 1 | from utils import convertResult, to32Hex, convertOr, convertDict, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hHeap": { 8 | "description": "操作堆的句柄", 9 | "value": to32Hex(info["hHeap"], "NULL") 10 | }, 11 | "dwFlags": { 12 | "description": "释放选项", 13 | "value": convertOr(info["dwFlags"], convertDict["HeapOptions"]) 14 | }, 15 | "lpMem": { 16 | "description": "释放地址", 17 | "value": to32Hex(info["lpMem"], "NULL") 18 | }, 19 | "return": { 20 | "description": "释放结果", 21 | "value": convertResult(info["return"]) 22 | } 23 | } 24 | if "errorCode" in info: 25 | event["eventDescription"].update({ 26 | "errorCode": { 27 | "description": "错误代码", 28 | "value": formatErrorCode(info["errorCode"]) 29 | } 30 | }) 31 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapfree" 32 | event["description"] = "{}地释放了{}处内存".format( 33 | event["eventDescription"]["return"]["value"], 34 | event["eventDescription"]["lpMem"]["value"] 35 | ) 36 | -------------------------------------------------------------------------------- /public/Description/HeapDescription.py: -------------------------------------------------------------------------------- 1 | from Description.Heap.HeapAlloc import description as heapAlloc 2 | from Description.Heap.HeapCreate import description as heapCreate 3 | from Description.Heap.HeapDestroy import description as heapDestroy 4 | from Description.Heap.HeapFree import description as heapFree 5 | 6 | 7 | def heapDescription(event): 8 | info = event["event"] 9 | operation = info["Operation"] 10 | if operation == "HeapAlloc": 11 | heapAlloc(event) 12 | elif operation == "HeapCreate": 13 | heapCreate(event) 14 | elif operation == "HeapDestroy": 15 | heapDestroy(event) 16 | elif operation == "HeapFree": 17 | heapFree(event) 18 | -------------------------------------------------------------------------------- /public/Description/HookFunc/StartTrace.py: -------------------------------------------------------------------------------- 1 | from utils import toMemorySize 2 | import time 3 | 4 | 5 | def convertTime(timeStamp): 6 | timeArray = time.localtime(timeStamp) 7 | return time.strftime("%Y/%m/%d %H:%M:%S", timeArray) 8 | 9 | 10 | def description(event): 11 | info = event["event"] 12 | event["eventDescription"] = { 13 | "cwd": { 14 | "description": "工作目录", 15 | "value": event["cwd"] 16 | }, 17 | "file": { 18 | "description": "当前文件绝对路径", 19 | "value": event["file"] 20 | }, 21 | 22 | } 23 | if "st_size" in info: 24 | event["eventDescription"].update({ 25 | "st_size": { 26 | "description": "当前文件大小", 27 | "value": toMemorySize(info["st_size"]) 28 | }, 29 | "st_atime": { 30 | "description": "上次访问时间", 31 | "value": convertTime(info["st_atime"]) 32 | }, 33 | "st_mtime": { 34 | "description": "上次修改时间", 35 | "value": convertTime(info["st_mtime"]) 36 | }, 37 | "st_ctime": { 38 | "description": "创建时间", 39 | "value": convertTime(info["st_ctime"]) 40 | } 41 | }) 42 | event['description'] = "开始追踪目标程序行为" 43 | -------------------------------------------------------------------------------- /public/Description/HookFunc/StopTrace.py: -------------------------------------------------------------------------------- 1 | def description(event): 2 | event['description'] = "结束追踪目标程序行为" -------------------------------------------------------------------------------- /public/Description/HookFuncDescription.py: -------------------------------------------------------------------------------- 1 | from Description.HookFunc.StartTrace import description as StartTrace 2 | from Description.HookFunc.StopTrace import description as StopTrace 3 | 4 | 5 | def HookFuncDescription(event): 6 | operation = event["event"]["Operation"] 7 | if operation == "StartTrace": 8 | StartTrace(event) 9 | elif operation == "StopTrace": 10 | StopTrace(event) 11 | -------------------------------------------------------------------------------- /public/Description/MessageBox/MessageBoxA.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, to32Hex, convertDict, convertOr 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hWnd": { 8 | "description": "父窗口句柄", 9 | "value": to32Hex(info['hWnd'], "无父窗口") 10 | }, 11 | "lpText": { 12 | "description": "弹窗标题", 13 | "value": info['lpText'] 14 | }, 15 | "lpCaption": { 16 | "description": "弹窗内容", 17 | "value": info['lpCaption'] 18 | }, 19 | "uType": { 20 | "description": "弹窗样式选项(部分解析)", 21 | "value": convertOr(info['uType'], convertDict['MessageBoxType']) 22 | }, 23 | "return": { 24 | "description": "按下的按钮", 25 | "value": convertEqual(info['return'], convertDict['MessageBoxReturn']) 26 | } 27 | } 28 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxa" 29 | event["description"] = "弹了一个窗" 30 | -------------------------------------------------------------------------------- /public/Description/MessageBoxDescription.py: -------------------------------------------------------------------------------- 1 | from Description.MessageBox.MessageBoxA import description 2 | 3 | 4 | def MessageBoxDescription(event): 5 | description(event) 6 | -------------------------------------------------------------------------------- /public/Description/Regedit/RegCloseKey.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, convertDict, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hKey": { 8 | "description": "操作键句柄", 9 | "value": convertEqual(info["hKey"], convertDict["RegeditHkey"]) 10 | }, 11 | "return": { 12 | "description": "执行结果 [系统错误代码]", 13 | "value": formatErrorCode(info["status"]) 14 | } 15 | } 16 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey" 17 | event["description"] = "关闭了注册表句柄" 18 | -------------------------------------------------------------------------------- /public/Description/Regedit/RegCreateKeyExA.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, convertOr, convertDict, to32Hex, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hKey": { 8 | "description": "主键名称", 9 | "value": convertEqual(info["hKey"], convertDict["RegeditHkey"]) 10 | }, 11 | "lpSubKey": { 12 | "description": "子键名称", 13 | "value": info["lpSubKey"], 14 | }, 15 | "Reserved": { 16 | "description": "备用(为0)", 17 | "value": to32Hex(info["Reserved"], "NULL") 18 | }, 19 | "lpClass": { 20 | "description": "用户定义类类型", 21 | "value": info["lpClass"] 22 | }, 23 | "dwOptions": { 24 | "description": "创建参数", 25 | "value": convertOr(info["dwOptions"], convertDict["RegeditOptions"]) 26 | }, 27 | "samDesired": { 28 | "description": "申请访问权限", 29 | "value": convertOr(info["samDesired"], convertDict["RegeditKeyAccess"]) 30 | }, 31 | "lpSecurityAttributes": { 32 | "description": "安全参数结构指针", 33 | "value": to32Hex(info["lpSecurityAttributes"], "NULL") 34 | }, 35 | "phkResult": { 36 | "description": "返回操作句柄", 37 | "value": to32Hex(info["phkResult"]) 38 | }, 39 | "lpdwDisposition": { 40 | "description": "处置信息", 41 | "value": convertEqual(info["lpdwDisposition"], convertDict["RegeditDisposition"]) 42 | }, 43 | "return": { 44 | "description": "执行结果 [系统错误代码]", 45 | "value": formatErrorCode(info["status"]) 46 | } 47 | } 48 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeyexa" 49 | event["description"] = "创建/打开了注册表键值" 50 | -------------------------------------------------------------------------------- /public/Description/Regedit/RegOpenKeyExA.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, convertDict, convertOr, to32Hex 2 | from utils import formatErrorCode 3 | 4 | 5 | def description(event): 6 | info = event["event"] 7 | event["eventDescription"] = { 8 | "hKey": { 9 | "description": "主键名称", 10 | "value": convertEqual(info["hKey"], convertDict["RegeditHkey"]) 11 | }, 12 | "ulOptions": { 13 | "description": "创建参数", 14 | "value": convertOr(info["ulOptions"], convertDict["RegeditOptions"]) 15 | }, 16 | "samDesired": { 17 | "description": "申请访问权限", 18 | "value": convertOr(info["samDesired"], convertDict["RegeditKeyAccess"]) 19 | }, 20 | "phkResult": { 21 | "description": "返回操作句柄", 22 | "value": to32Hex(info["phkResult"]) 23 | }, 24 | "return": { 25 | "description": "执行结果 [系统错误代码]", 26 | "value": formatErrorCode(info["status"]) 27 | } 28 | } 29 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa" 30 | event["description"] = "打开了[{}]注册表键值".format( 31 | event["eventDescription"]["hKey"]["value"][-1] 32 | ) 33 | -------------------------------------------------------------------------------- /public/Description/Regedit/RegQueryValueExA.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, convertDict, to32Hex, toMemorySize, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hKey": { 8 | "description": "键值句柄", 9 | "value": convertEqual(info["hKey"], convertDict["RegeditHkey"]) 10 | }, 11 | "lpValueName": { 12 | "description": "键名", 13 | "value": info["lpValueName"] 14 | }, 15 | "lpReserved": { 16 | "description": "备用(NULL)", 17 | "value": to32Hex(info["lpReserved"], "NULL") 18 | }, 19 | "lpType": { 20 | "description": "键值类型指针", 21 | "value": to32Hex(info["lpType"], "NULL") 22 | }, 23 | "lpData": { 24 | "description": "键值内容", 25 | "value": to32Hex(info["lpData"]), 26 | "buffer": info.get("lpDataValue", "") 27 | }, 28 | "lpcbData": { 29 | "description": "内容长度", 30 | "value": toMemorySize(info["lpcbData"]) 31 | }, 32 | "return": { 33 | "description": "执行结果", 34 | "value": formatErrorCode(info["status"]) 35 | } 36 | } 37 | if "lpTypeValue" in info: 38 | event["eventDescription"]["lpType"] = { 39 | "description": "键值类型指针", 40 | "value": convertEqual(info["lpTypeValue"], convertDict["RegeditType"]) 41 | } 42 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa" 43 | event["description"] = "读取注册表句柄{}下{}键值".format( 44 | event["eventDescription"]["hKey"]["value"][-1], 45 | event["eventDescription"]["lpValueName"]["value"], 46 | ) 47 | -------------------------------------------------------------------------------- /public/Description/Regedit/RegSetValueExA.py: -------------------------------------------------------------------------------- 1 | from utils import convertEqual, convertDict, to32Hex, toMemorySize, formatErrorCode 2 | 3 | 4 | def description(event): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "hKey": { 8 | "description": "键值句柄", 9 | "value": convertEqual(info["hKey"], convertDict["RegeditHkey"]) 10 | }, 11 | "lpValueName": { 12 | "description": "键名", 13 | "value": info["lpValueName"] 14 | }, 15 | "Reserved": { 16 | "description": "备用(NULL)", 17 | "value": to32Hex(info["Reserved"], "NULL") 18 | }, 19 | "dwType": { 20 | "description": "键值类型", 21 | "value": convertEqual(info["dwType"], convertDict["RegeditType"]) 22 | }, 23 | "lpData": { 24 | "description": "键值内容", 25 | "value": to32Hex(info["lpData"]), 26 | "buffer": info.get("lpDataValue", "") 27 | }, 28 | "cbData": { 29 | "description": "内容长度", 30 | "value": toMemorySize(info["cbData"]) 31 | }, 32 | "return": { 33 | "description": "执行结果", 34 | "value": formatErrorCode(info["status"]) 35 | } 36 | } 37 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexa" 38 | event["description"] = "写注册表句柄{}下{}键值".format( 39 | event["eventDescription"]["hKey"]["value"][-1], 40 | event["eventDescription"]["lpValueName"]["value"], 41 | ) 42 | -------------------------------------------------------------------------------- /public/Description/RegeditDescription.py: -------------------------------------------------------------------------------- 1 | from Description.Regedit.RegCloseKey import description as regCloseKey 2 | from Description.Regedit.RegCreateKeyExA import description as regCreateKeyExA 3 | from Description.Regedit.RegOpenKeyExA import description as regOpenKeyExA 4 | from Description.Regedit.RegQueryValueExA import description as regQueryValueExA 5 | from Description.Regedit.RegSetValueExA import description as regSetValueExA 6 | 7 | def regEditDescription(event): 8 | operation = event["event"]["Operation"] 9 | if operation == "RegCloseKey": 10 | regCloseKey(event) 11 | elif operation == "RegCreateKeyExA": 12 | regCreateKeyExA(event) 13 | elif operation == "RegOpenKeyExA": 14 | regOpenKeyExA(event) 15 | elif operation == "RegQueryValueExA": 16 | regQueryValueExA(event) 17 | elif operation == "RegSetValueExA": 18 | regSetValueExA(event) -------------------------------------------------------------------------------- /public/Description/Socket/WSACleanup.py: -------------------------------------------------------------------------------- 1 | from utils import to32Hex, convertResult, formatErrorCode 2 | 3 | 4 | def join(primary, secondary): 5 | return "{}.{}".format(primary, secondary) 6 | 7 | 8 | def description(event, socketList: dict): 9 | info = event["event"] 10 | event["eventDescription"] = { 11 | "return": { 12 | "description": "执行结果", 13 | "value": convertResult(info["status"], reverse=True) 14 | } 15 | } 16 | if "errorCode" in info: 17 | event["eventDescription"].update({ 18 | "errorCode": { 19 | "description": "错误代码", 20 | "value": formatErrorCode(info["errorCode"]) 21 | } 22 | }) 23 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsacleanup" 24 | event["description"] = "清理套接字" 25 | -------------------------------------------------------------------------------- /public/Description/Socket/WSAStartup.py: -------------------------------------------------------------------------------- 1 | from utils import to32Hex, convertResult, formatErrorCode 2 | 3 | 4 | def join(primary, secondary): 5 | return "{}.{}".format(primary, secondary) 6 | 7 | 8 | def description(event, socketList: dict): 9 | info = event["event"] 10 | event["eventDescription"] = { 11 | "wVersionRequired": { 12 | "description": "请求的套接字版本号", 13 | "value": [to32Hex(info["wVersionRequired"]), join(info["wVersionRequiredPrimary"], 14 | info["wVersionRequiredSecondary"])] 15 | }, 16 | "wVersion": { 17 | "description": "返回的套接字版本号", 18 | "value": "[未返回]" 19 | }, 20 | "lpWSAData": { 21 | "description": "套接字信息结构地址", 22 | "value": to32Hex(info["lpWSAData"], "NULL") 23 | }, 24 | "return": { 25 | "description": "执行结果", 26 | "value": formatErrorCode(info["status"]) 27 | } 28 | } 29 | if info["lpWSAData"] != 0 and info["status"] != 10014: 30 | event["eventDescription"]["wVersion"]["value"] = [to32Hex(info["wVersion"]), join(info["wVersionPrimary"], 31 | info["wVersionSecondary"])] 32 | event["eventDescription"]["lpWSAData"]["buffer"] = info["lpWSADataValue"] 33 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup" 34 | event["description"] = "初始化套接字" 35 | -------------------------------------------------------------------------------- /public/Description/Socket/closesocket.py: -------------------------------------------------------------------------------- 1 | from utils import to32Hex, convertResult, formatErrorCode 2 | 3 | 4 | def join(primary, secondary): 5 | return "{}.{}".format(primary, secondary) 6 | 7 | 8 | def description(event, socketList: dict): 9 | info = event["event"] 10 | event["eventDescription"] = { 11 | "s": { 12 | "description": "连接的套接字", 13 | "value": [to32Hex(info["s"]), socketList.get(info["s"], "[UnKnown]")] 14 | }, 15 | "return": { 16 | "description": "执行结果", 17 | "value": convertResult(info["status"], reverse=True) 18 | } 19 | } 20 | if "errorCode" in info: 21 | event["eventDescription"].update({ 22 | "errorCode": { 23 | "description": "错误代码", 24 | "value": formatErrorCode(info["errorCode"]) 25 | } 26 | }) 27 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-closesocket" 28 | event["description"] = "关闭套接字 {}".format(event["eventDescription"]["s"]["value"][-1]) 29 | -------------------------------------------------------------------------------- /public/Description/Socket/connect.py: -------------------------------------------------------------------------------- 1 | from utils import convertDict, convertResult, convertEqual, to32Hex, joinSocketAddr, formatErrorCode,toMemorySize 2 | 3 | 4 | def description(event, socketList): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "s": { 8 | "description": "连接的套接字", 9 | "value": to32Hex(info["s"]) 10 | }, 11 | "name": { 12 | "description": "套接字连接信息指针", 13 | "value": to32Hex(info["sockaddr"]) 14 | }, 15 | "namelen": { 16 | "description": "套接字连接信息长度", 17 | "value": toMemorySize(info["namelen"]) 18 | } 19 | } 20 | 21 | event["description"] = "套接字连接 [无法解析地址]" 22 | 23 | if "sa_family" in info: 24 | 25 | event["eventDescription"].update( 26 | { 27 | "sa_family": { 28 | "description": "连接地址族规范", 29 | "value": convertEqual(info["sa_family"], convertDict["SocketAf"]) 30 | } 31 | } 32 | ) 33 | event["eventDescription"]["name"]["buffer"] = info["nameValue"] 34 | 35 | if "sin_addr" in info: 36 | 37 | event["eventDescription"]["sin_addr"] = { 38 | "description": "连接目标", 39 | "value": joinSocketAddr(info["sin_addr"], info["sin_port"]) 40 | } 41 | 42 | event["description"] = "套接字连接 {}".format(event["eventDescription"]["sin_addr"]["value"]) 43 | socketList[info["s"]] = event["eventDescription"]["sin_addr"]["value"] 44 | 45 | event["eventDescription"].update( 46 | { 47 | "return": { 48 | "description": "执行结果", 49 | "value": convertResult(info["status"], reverse=True) 50 | } 51 | } 52 | ) 53 | 54 | if "errorCode" in info: 55 | event["eventDescription"].update({ 56 | "errorCode": { 57 | "description": "错误代码", 58 | "value": formatErrorCode(info["errorCode"]) 59 | } 60 | }) 61 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect" 62 | -------------------------------------------------------------------------------- /public/Description/Socket/recv.py: -------------------------------------------------------------------------------- 1 | from utils import convertResult, toMemorySize, to32Hex, formatErrorCode 2 | 3 | 4 | def checkReturn(status): 5 | if status >= 0: 6 | return toMemorySize(status) 7 | else: 8 | return "[SOCKET_ERROR]" 9 | 10 | 11 | def description(event, socketList): 12 | info = event["event"] 13 | event["eventDescription"] = { 14 | "s": { 15 | "description": "连接的套接字", 16 | "value": [to32Hex(info["s"]), socketList.get(info["s"], "[UnKnown]")] 17 | }, 18 | "buf": { 19 | "description": "缓冲区地址", 20 | "value": to32Hex(info["buf"]), 21 | "buffer": info.get('bufValue', "") 22 | }, 23 | "len": { 24 | "description": "缓冲区长度", 25 | "value": toMemorySize(info["len"]) 26 | }, 27 | "flags": { 28 | "description": "函数执行参数标志", 29 | "value": to32Hex(info["flags"]) 30 | }, 31 | "return": { 32 | "description": "接受字节数", 33 | "value": checkReturn(info["status"]) 34 | } 35 | } 36 | if "errorCode" in info: 37 | event["eventDescription"].update({ 38 | "errorCode": { 39 | "description": "错误代码", 40 | "value": formatErrorCode(info["errorCode"]) 41 | } 42 | }) 43 | event["description"] = "套接字接受来自 {} 的信息".format(event["eventDescription"]["s"]["value"][-1]) 44 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv" 45 | -------------------------------------------------------------------------------- /public/Description/Socket/send.py: -------------------------------------------------------------------------------- 1 | from utils import convertResult, toMemorySize, to32Hex, formatErrorCode 2 | 3 | 4 | def checkReturn(status): 5 | if status >= 0: 6 | return toMemorySize(status) 7 | else: 8 | return "[SOCKET_ERROR]" 9 | 10 | 11 | def description(event, socketList): 12 | info = event["event"] 13 | event["eventDescription"] = { 14 | "s": { 15 | "description": "连接的套接字", 16 | "value": [to32Hex(info["s"]), socketList.get(info["s"], "[UnKnown]")] 17 | }, 18 | "buf": { 19 | "description": "缓冲区地址", 20 | "value": to32Hex(info["buf"]), 21 | "buffer": info.get('bufValue', "") 22 | }, 23 | "len": { 24 | "description": "缓冲区长度", 25 | "value": toMemorySize(info["len"]) 26 | }, 27 | "flags": { 28 | "description": "函数执行参数标志", 29 | "value": to32Hex(info["flags"]) 30 | }, 31 | "return": { 32 | "description": "发送字节数", 33 | "value": checkReturn(info["status"]) 34 | } 35 | } 36 | if "errorCode" in info: 37 | event["eventDescription"].update({ 38 | "errorCode": { 39 | "description": "错误代码", 40 | "value": formatErrorCode(info["errorCode"]) 41 | } 42 | }) 43 | event["description"] = "套接字发送信息到 {}".format(event["eventDescription"]["s"]["value"][-1]) 44 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send" 45 | -------------------------------------------------------------------------------- /public/Description/Socket/socket.py: -------------------------------------------------------------------------------- 1 | from utils import convertDict, convertEqual, formatErrorCode 2 | 3 | 4 | def description(event, socketList: dict): 5 | info = event["event"] 6 | event["eventDescription"] = { 7 | "af": { 8 | "description": "地址族规范", 9 | "value": convertEqual(info["af"], convertDict["SocketAf"]) 10 | }, 11 | "type": { 12 | "description": "套接字的类型规范", 13 | "value": convertEqual(info["type"], convertDict["SocketType"]) 14 | }, 15 | "protocol": { 16 | "description": "要使用的协议", 17 | "value": convertEqual(info["protocol"], convertDict["SocketProtocol"]) 18 | }, 19 | "return": { 20 | "description": "socket描述符", 21 | "value": convertEqual(info["socket"], convertDict["SocketInfo"]) 22 | } 23 | } 24 | if "errorCode" in info: 25 | event["eventDescription"].update({ 26 | "errorCode": { 27 | "description": "错误代码", 28 | "value": formatErrorCode(info["errorCode"]) 29 | } 30 | }) 31 | event["document"] = "https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket" 32 | event["description"] = "新建了一个套接字" 33 | -------------------------------------------------------------------------------- /public/Description/SocketDescription.py: -------------------------------------------------------------------------------- 1 | from Description.Socket.WSACleanup import description as WSACleanup 2 | from Description.Socket.WSAStartup import description as WSAStartup 3 | from Description.Socket.closesocket import description as closesocket 4 | from Description.Socket.connect import description as connect 5 | from Description.Socket.recv import description as recv 6 | from Description.Socket.send import description as send 7 | from Description.Socket.socket import description as socket 8 | 9 | 10 | def SocketDescription(event,socketDict): 11 | operation = event["event"]["Operation"] 12 | if operation == "socket": 13 | socket(event, socketDict) 14 | elif operation == "WSAStartup": 15 | WSAStartup(event, socketDict) 16 | elif operation == "connect": 17 | connect(event, socketDict) 18 | elif operation == "recv": 19 | recv(event, socketDict) 20 | elif operation == "send": 21 | send(event, socketDict) 22 | elif operation == "closesocket": 23 | closesocket(event, socketDict) 24 | elif operation == "WSACleanup": 25 | WSACleanup(event, socketDict) 26 | -------------------------------------------------------------------------------- /public/Handlers/FileHandler.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from Description.FileDescription import FileDescription 4 | from utils import WarningEmit, to32Hex 5 | 6 | Sensitive_suffix = (".exe", ".sys", ".com", ".bat", ".dll", ".vbs", ".ocx") 7 | 8 | 9 | def to_abs_path(cwd, path): 10 | if os.path.isabs(path): 11 | return path 12 | else: 13 | return os.path.join(cwd, path) 14 | 15 | 16 | class FileHandler: 17 | def __init__(self): 18 | self.name = "File" 19 | self.fileHandleMap = {} 20 | 21 | def event_handler(self, event): 22 | 23 | # 不处理不属于Heap Event的操作 24 | if event["eventID"] != self.name: 25 | WarningEmit("Danger", 1, "错误的Handler") 26 | return 27 | 28 | FileDescription(event) 29 | info = event["event"] 30 | operationPath = "" 31 | 32 | if info["Operation"] == "CreateFileA": 33 | if info["handle"] == -1: 34 | WarningEmit(event, "Warning", 211, "未成功创建文件") 35 | operationPath = info["path"] 36 | self.fileHandleMap[info["handle"]] = operationPath 37 | 38 | elif info["Operation"] == "OpenFile": 39 | if info["hFile"] == -1: 40 | WarningEmit(event, "Warning", 211, "未成功创建文件") 41 | WarningEmit(event, "Warning", 212, "使用过时的Win32API") 42 | operationPath = to_abs_path( 43 | event["cwd"], info["lpFileName"]) 44 | self.fileHandleMap[info["hFile"]] = operationPath 45 | 46 | elif info["Operation"] == "_lclose": 47 | if not info["return"]: 48 | WarningEmit(event, "Warning", 213, "未成功关闭文件") 49 | WarningEmit(event, "Warning", 212, "使用过时的Win32API") 50 | operationPath = self.fileHandleMap.pop(info["hFile"], "") 51 | 52 | elif info["Operation"] == "CloseHandle": 53 | if info["return"] == 0: 54 | WarningEmit(event, "Warning", 213, "未成功关闭文件") 55 | self.fileHandleMap.pop(info["hFile"], "") 56 | operationPath = info["path"] 57 | 58 | else: 59 | if info["return"] == 0: 60 | WarningEmit(event, "Warning", 214, "未成功执行指令") 61 | operationPath = info["path"] 62 | 63 | if operationPath != "": 64 | if os.path.samefile(operationPath, event["file"]): 65 | WarningEmit(event, "Danger", 201, "使用自身作为目标文件") 66 | 67 | dirname = os.path.dirname(operationPath) 68 | for file in os.listdir(dirname): 69 | if os.path.isdir(os.path.join(dirname, file)): 70 | WarningEmit(event, "Warning", 215, "目标文件所在目录存在目录") 71 | break 72 | 73 | if operationPath.endswith(Sensitive_suffix): 74 | WarningEmit(event, "Danger", 202, "目标文件是敏感后缀文件") 75 | else: 76 | WarningEmit(event, "Warning", 216, "未追踪的文件句柄") 77 | 78 | return {} 79 | 80 | def fin_event_handler(self, event): 81 | if len(self.fileHandleMap) > 0: 82 | unfree_handler = [] 83 | for k in self.fileHandleMap: 84 | unfree_handler.append(to32Hex(k)) 85 | WarningEmit(event, "Warning", 217, "未释放所有的文件句柄", unfree_handler) 86 | return {} 87 | -------------------------------------------------------------------------------- /public/Handlers/HeapHandler.py: -------------------------------------------------------------------------------- 1 | from Description.HeapDescription import heapDescription 2 | from utils import WarningEmit, to32Hex 3 | 4 | 5 | class HeapHandler: 6 | def __init__(self): 7 | self.name = "Heap" 8 | self.heap_map = {} 9 | self.heap_alloc_map = {} 10 | 11 | def event_handler(self, event): 12 | # 不处理不属于Heap Event的操作 13 | if event["eventID"] != self.name: 14 | WarningEmit(event, "Danger", 1, "错误的Handler") 15 | return 16 | 17 | info = event["event"] 18 | hHeap = info["hHeap"] 19 | heapDescription(event) 20 | 21 | # heapCreate 22 | if info["Operation"] == "HeapCreate": 23 | 24 | if hHeap != 0: 25 | self.heap_map[hHeap] = True # 对Create的Heap开始追踪 26 | self.heap_alloc_map[hHeap] = {} 27 | else: 28 | # hHeap为0(NULL),创建Heap失败 29 | WarningEmit(event, "Warning", 111, "未成功创建堆") 30 | 31 | elif info["Operation"] == "HeapAlloc": 32 | 33 | if self.heap_map.get(hHeap, False): 34 | if info["address"] != 0: 35 | self.heap_alloc_map[hHeap][info["address"]] = True # 对Alloc的内存开始追踪 36 | else: 37 | # address为0(NULL),申请内存失败 38 | WarningEmit(event, "Warning", 112, "未成功申请到内存") 39 | else: 40 | # 对Destroy的hHeap操作 41 | WarningEmit(event, "Danger", 101, "在不存在的堆上申请内存") 42 | 43 | elif info["Operation"] == "HeapDestroy": 44 | 45 | if self.heap_map.get(hHeap, False): 46 | self.heap_map.pop(hHeap) # 取消对该堆的追踪 47 | if len(self.heap_alloc_map[hHeap]) != 0: # 检查该堆是否有未释放内存 48 | unfree_address = [] 49 | for k in self.heap_alloc_map[hHeap]: 50 | unfree_address.append(to32Hex(k)) 51 | self.heap_alloc_map[hHeap] = {} # 手动清空 52 | WarningEmit(event, "Warning", 113, 53 | "摧毁堆时有内存未释放[无害]", unfree_address) 54 | else: 55 | WarningEmit(event, "Danger", 102, 56 | "试图摧毁不存在的堆") # 发现调用不存在Heap 57 | 58 | elif info["Operation"] == "HeapFree": 59 | if self.heap_map.get(hHeap, False): 60 | if self.heap_alloc_map[hHeap].get(info["lpMem"], False): 61 | self.heap_alloc_map[hHeap].pop(info["lpMem"]) # 取消对该地址的追踪 62 | else: 63 | WarningEmit(event, "Danger", 103, 64 | "试图释放未分配的地址") # 该地址已释放再次释放 65 | else: 66 | WarningEmit(event, "Danger", 104, "在不存在得堆上释放地址") # 发现调用不存在Heap 67 | 68 | else: 69 | WarningEmit(event, "Danger", 2, "无可用Operation") # 不太可能到这里 70 | 71 | return {} 72 | 73 | def fin_event_handler(self, event): 74 | if len(self.heap_map) != 0: 75 | unfree_heap = [] 76 | for k in self.heap_map: 77 | unfree_heap.append(to32Hex(k)) 78 | WarningEmit(event, "Warning", 114, "应用结束时有堆未被摧毁", unfree_heap) 79 | return {} 80 | -------------------------------------------------------------------------------- /public/Handlers/HookFuncHandler.py: -------------------------------------------------------------------------------- 1 | from utils import WarningEmit 2 | from Description.HookFuncDescription import HookFuncDescription 3 | 4 | 5 | class HookFuncHandler: 6 | def __init__(self): 7 | self.name = "HookFunc" 8 | 9 | def event_handler(self, event): 10 | if event["eventID"] != self.name: 11 | WarningEmit(event, "Danger", 1, "错误的Handler") 12 | return 13 | HookFuncDescription(event) 14 | 15 | def fin_event_handler(self, event): 16 | pass 17 | -------------------------------------------------------------------------------- /public/Handlers/MessageBoxHandler.py: -------------------------------------------------------------------------------- 1 | from utils import WarningEmit 2 | from Description.MessageBoxDescription import description 3 | 4 | 5 | class MessageBoxHandler: 6 | def __init__(self): 7 | self.name = "MessageBox" 8 | 9 | def event_handler(self, event): 10 | if event["eventID"] != self.name: 11 | WarningEmit(event, "Danger", 1, "错误的Handler") 12 | return 13 | description(event) 14 | 15 | def fin_event_handler(self, event): 16 | pass 17 | -------------------------------------------------------------------------------- /public/Handlers/RegHandler.py: -------------------------------------------------------------------------------- 1 | from utils import WarningEmit 2 | from Description.RegeditDescription import regEditDescription 3 | 4 | 5 | class RegHandler: 6 | def __init__(self): 7 | self.name = "Regedit" 8 | 9 | def event_handler(self, event): 10 | if event["eventID"] != self.name: 11 | WarningEmit(event, "Danger", 1, "错误的Handler") 12 | return 13 | 14 | regEditDescription(event) 15 | info = event["event"] 16 | 17 | if info["status"] != 0: 18 | WarningEmit(event, "Warning", 311, "未成功修改注册表项") 19 | 20 | if info.get("lpSubKey", "").lower() == "SOFTWARE\Microsoft\Windows\CurrentVersion\Run".lower(): 21 | WarningEmit(event, "Danger", 301, "试图修改启动项") 22 | 23 | def fin_event_handler(self, event): 24 | pass 25 | -------------------------------------------------------------------------------- /public/Handlers/SocketHandler.py: -------------------------------------------------------------------------------- 1 | from utils import WarningEmit 2 | from Description.SocketDescription import SocketDescription 3 | 4 | 5 | class SocketHandler: 6 | def __init__(self): 7 | self.name = "Socket" 8 | self.socketDict = {} 9 | 10 | def event_handler(self, event): 11 | if event["eventID"] != self.name: 12 | WarningEmit(event, "Danger", 1, "错误的Handler") 13 | return 14 | SocketDescription(event,self.socketDict) 15 | 16 | def fin_event_handler(self, event): 17 | pass 18 | -------------------------------------------------------------------------------- /public/handleMain.py: -------------------------------------------------------------------------------- 1 | from Handlers.MessageBoxHandler import MessageBoxHandler 2 | from Handlers.RegHandler import RegHandler 3 | from Handlers.FileHandler import FileHandler 4 | from Handlers.HeapHandler import HeapHandler 5 | from Handlers.SocketHandler import SocketHandler 6 | from Handlers.HookFuncHandler import HookFuncHandler 7 | 8 | 9 | class Handler: 10 | def __init__(self): 11 | self.handler_name = "undefined" 12 | self.messageBox_handler = MessageBoxHandler() 13 | self.heap_handler = HeapHandler() 14 | self.file_handler = FileHandler() 15 | self.reg_handler = RegHandler() 16 | self.socket_handler = SocketHandler() 17 | self.hook_func_handler = HookFuncHandler() 18 | 19 | def event_handle(self, event): 20 | if event["eventID"] == "MessageBox": 21 | self.messageBox_handler.event_handler(event) 22 | if event["eventID"] == "Heap": 23 | self.heap_handler.event_handler(event) 24 | elif event["eventID"] == "File": 25 | self.file_handler.event_handler(event) 26 | elif event["eventID"] == "Regedit": 27 | self.reg_handler.event_handler(event) 28 | elif event["eventID"] == "HookFunc": 29 | self.hook_func_handler.event_handler(event) 30 | if event["event"]["Operation"] == "StopTrace": 31 | self.fin_event_handle(event) 32 | elif event["eventID"] == "Socket": 33 | self.socket_handler.event_handler(event) 34 | 35 | def fin_event_handle(self, event): 36 | self.messageBox_handler.fin_event_handler(event) 37 | self.heap_handler.fin_event_handler(event) 38 | self.file_handler.fin_event_handler(event) 39 | self.reg_handler.fin_event_handler(event) 40 | -------------------------------------------------------------------------------- /public/main.py: -------------------------------------------------------------------------------- 1 | import pipeThread 2 | from concurrent.futures import ThreadPoolExecutor 3 | from flask import Flask, request,render_template 4 | from flask_socketio import SocketIO, emit 5 | import subprocess 6 | import ctypes 7 | import sys 8 | import os 9 | from flask_cors import CORS, cross_origin 10 | 11 | app = Flask(__name__, static_url_path='/', static_folder='..\\src\\web\\dist\\spa',template_folder='..\\src\\web\\dist\\spa') 12 | CORS(app) 13 | socketio = SocketIO(app, cors_allowed_origins='*',async_mode="threading") 14 | executor = ThreadPoolExecutor(2) 15 | targetProcess = None 16 | targetThread = None 17 | 18 | 19 | def stopTarget(): 20 | global targetProcess 21 | if targetProcess is not None: 22 | if pipeThread.getPid() != 0: 23 | os.popen('taskkill.exe /pid:' + str(pipeThread.getPid())) 24 | targetProcess.terminate() 25 | 26 | 27 | @app.route('/') 28 | def index(): 29 | return render_template("index.html") 30 | 31 | 32 | @app.route('/trace/') 33 | def Trace(command): 34 | global targetProcess, targetThread, socketio 35 | path = request.args.get( 36 | 'path', '') 37 | if command == "start": 38 | stopTarget() 39 | if os.path.exists(path): 40 | targetProcess = subprocess.Popen(["H:\\softwareSecurityTask\\src\\Injector\\Debug\\Injector.exe", 41 | path], shell=True) 42 | executor.submit(pipeThread.pipeThread, socketio) 43 | return {"result": True} 44 | else: 45 | return {"result": False} 46 | elif command == "stop": 47 | stopTarget() 48 | return {"result": True} 49 | 50 | 51 | @socketio.on('connect') 52 | def test_message(message): 53 | emit('ConnectInfo', {'data': "Hello SocketIO"}) 54 | 55 | 56 | # python 3 Only! 57 | def is_admin(): 58 | try: 59 | return ctypes.windll.shell32.IsUserAnAdmin() 60 | except: 61 | return False 62 | 63 | 64 | WebStart = False 65 | 66 | if __name__ == '__main__': 67 | if is_admin(): 68 | socketio.run(app, debug=True, host='0.0.0.0', port=9013) 69 | else: 70 | ctypes.windll.shell32.ShellExecuteW( 71 | None, "runas", sys.executable, __file__, None, 1) 72 | -------------------------------------------------------------------------------- /public/pipeThread.py: -------------------------------------------------------------------------------- 1 | from handleMain import Handler 2 | from Handlers.RegHandler import RegHandler 3 | from Handlers.HeapHandler import HeapHandler 4 | from Handlers.FileHandler import FileHandler 5 | import win32file 6 | import win32pipe 7 | import json 8 | 9 | pid = 0 10 | eventUID = 1 11 | 12 | 13 | def getPid(): 14 | global pid 15 | return pid 16 | 17 | 18 | def pipeThread(sio): 19 | global pid, eventUID 20 | pid = 0 21 | PIPE_NAME = r'\\.\Pipe\mypipe' 22 | PIPE_BUFFER_SIZE = 65535 23 | named_pipe = win32pipe.CreateNamedPipe(PIPE_NAME, 24 | win32pipe.PIPE_ACCESS_DUPLEX, 25 | win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT | win32pipe.PIPE_READMODE_MESSAGE, 26 | win32pipe.PIPE_UNLIMITED_INSTANCES, 27 | PIPE_BUFFER_SIZE, 28 | PIPE_BUFFER_SIZE, 500, None) 29 | event_handler = Handler() 30 | eventUID = 1 31 | try: 32 | while True: 33 | rawjson = dict() 34 | try: 35 | win32pipe.ConnectNamedPipe(named_pipe, None) 36 | data = win32file.ReadFile( 37 | named_pipe, PIPE_BUFFER_SIZE, None) 38 | 39 | if data is None or len(data) < 2: 40 | continue 41 | 42 | # print('receive msg:', data) 43 | # print(str(data[1])); 44 | 45 | rawstr = data[1].decode() 46 | rawstr = rawstr.replace("\x00", "") 47 | # rawstr = rawstr.replace("\\\\","\\") 48 | rawjson = json.loads(rawstr) 49 | if pid == 0: 50 | pid = rawjson["pid"] 51 | # print(rawjson) 52 | rawjson['warnings'] = [] 53 | rawjson['warningLevel'] = 0 54 | rawjson['description'] = "" 55 | rawjson['eventDescription'] = {} 56 | rawjson['id'] = eventUID 57 | eventUID = eventUID + 1 58 | event_handler.event_handle(rawjson) 59 | sio.emit('DetourEvent', {'data': rawjson}) 60 | 61 | except BaseException as e: 62 | print("exception:", e) 63 | event_handler.fin_event_handle(rawjson) 64 | break 65 | finally: 66 | try: 67 | print("断开了管道连接") 68 | win32pipe.DisconnectNamedPipe(named_pipe) 69 | except: 70 | pass 71 | -------------------------------------------------------------------------------- /public/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/public/requirements.txt -------------------------------------------------------------------------------- /public/template/index.html: -------------------------------------------------------------------------------- 1 | Quasar App
-------------------------------------------------------------------------------- /public/utils.py: -------------------------------------------------------------------------------- 1 | import win32api 2 | 3 | convertDict = { 4 | "MessageBoxType": { 5 | 0x00000002: "MB_ABORTRETRYIGNORE [中止/重试/忽略]", 6 | 0x00000006: "MB_CANCELTRYCONTINUE [取消/重试/继续]", 7 | 0x00004000: "MB_HELP [添加帮助按钮]", 8 | 0x00000000: "MB_OK [确定]", 9 | 0x00000001: "MB_OKCANCEL [确定/取消]", 10 | 0x00000005: "MB_RETRYCANCEL [重试/取消]", 11 | 0x00000004: "MB_YESNO [是/否]", 12 | 0x00000003: "MB_YESNOCANCEL [是/否/取消]" 13 | }, 14 | "MessageBoxReturn": { 15 | 3: "IDABORT [中止]", 16 | 2: "IDCANCEL [取消]", 17 | 11: "IDCONTINUE [继续]", 18 | 5: "IDIGNORE [忽略]", 19 | 7: "IDNO [否]", 20 | 1: "IDOK [确定]", 21 | 4: "IDRETRY [重试]", 22 | 10: "IDTRYAGAIN [重试]", 23 | 6: "IDYES [是]" 24 | }, 25 | "HeapOptions": { 26 | 0x00040000: "HEAP_CREATE_ENABLE_EXECUTE [关闭数据执行保护]", 27 | 0x00000004: "HEAP_GENERATE_EXCEPTIONS [调用失败时引发异常]", 28 | 0x00000001: "HEAP_NO_SERIALIZE [不使用序列化访问]", 29 | 0x00000008: "HEAP_ZERO_MEMORY [初始化为0]" 30 | }, 31 | "FileAccessMask": { 32 | 0x80000000: "GENERIC_READ [一般读权限]", 33 | 0x40000000: "GENERIC_WRITE [一搬写权限]" 34 | }, 35 | "FileShareMode": { 36 | 0x00000000: "0 [阻止其它进程访问]", 37 | 0x00000004: "FILE_SHARE_DELETE [允许删除访问权限]", 38 | 0x00000001: "FILE_SHARE_READ [允许读取访问权限]", 39 | 0x00000002: "FILE_SHARE_WRITE [允许写访问权限]" 40 | }, 41 | "FileCreationDisposition": { 42 | 2: "CREATE_ALWAYS [总是创建文件]", 43 | 1: "CREATE_NEW [不存在时创建文件]", 44 | 4: "OPEN_ALWAYS [总是打开文件]", 45 | 3: "OPEN_EXISTING [文件存在时打开文件]", 46 | 5: "TRUNCATE_EXISTING [文件存在时清空文件]" 47 | }, 48 | "FileFlagsAndAttributes": { 49 | 128: "FILE_ATTRIBUTE_NORMAL [无属性]", 50 | }, 51 | "RegeditHkey": { 52 | 0x80000000: "HKEY_CLASSES_ROOT", 53 | 0x80000005: "HKEY_CURRENT_CONFIG", 54 | 0x80000001: "HKEY_CURRENT_USER", 55 | 0x80000002: "HKEY_LOCAL_MACHINE", 56 | 0x80000003: "HKEY_USERS" 57 | }, 58 | "RegeditOptions": { 59 | 0x00000000: "REG_OPTION_NON_VOLATILE [此键不易失]", 60 | 0x00000001: "REG_OPTION_VOLATILE [此键易失]", 61 | 0x00000002: "REG_OPTION_CREATE_LINK [此键为符号链接]", 62 | 0x00000004: "REG_OPTION_BACKUP_RESTORE [使用备份/恢复权限打开]", 63 | 0x00000008: "REG_OPTION_OPEN_LINK [此键为符号链接]" 64 | }, 65 | "RegeditKeyAccess": { 66 | 0xF003F: "KEY_ALL_ACCESS [全部权限]", 67 | 0x20019: "KEY_READ [读取键相关权限]", 68 | 0x20006: "KEY_WRITE [写键相关权限]", 69 | 0x0020: "KEY_CREATE_LINK [保留供系统使用]", 70 | 0x0004: "KEY_CREATE_SUB_KEY [创建子项]", 71 | 0x0008: "KEY_ENUMERATE_SUB_KEYS [枚举子项]", 72 | 0x0010: "KEY_NOTIFY [请求更改通知]", 73 | 0x0001: "KEY_QUERY_VALUE [查询值]", 74 | 0x0002: "KEY_SET_VALUE [设置值]", 75 | 0x0000: "NULL [继承父键]" 76 | }, 77 | "RegeditDisposition": { 78 | 0x00000000: "无处置信息", 79 | 0x00000001: "REG_CREATED_NEW_KEY [键不存在并已创建]", 80 | 0x00000002: "REG_OPENED_EXISTING_KEY [键存在并打开]" 81 | }, 82 | "RegeditType": { 83 | 0: "REG_NONE [无类型]", 84 | 1: "REG_SZ [Unicode字符串]", 85 | 2: "REG_EXPAND_SZ [含环境变量字符串]", 86 | 3: "REG_BINARY [二进制类型]", 87 | 4: "REG_DWORD [32位字符]", 88 | 5: "REG_DWORD_BIG_ENDIAN [32位大端存储]", 89 | 6: "REG_LINK [含符号字符串]", 90 | 7: "REG_MULTI_SZ [多个字符串]", 91 | 11: "REG_QWORD [64位数字]", 92 | }, 93 | "SocketAf": { 94 | 0: "AF_UNSPEC [地址族未指定]", 95 | 2: "AF_INET [IPV4]", 96 | 23: "AF_INET6 [IPV6]" 97 | }, 98 | "SocketType": { 99 | 1: "SOCK_STREAM", 100 | 2: "SOCK_DGRAM", 101 | 3: "SOCK_RAW", 102 | 4: "SOCK_RDM", 103 | 5: "SOCK_SEQPACKET", 104 | }, 105 | "SocketProtocol": { 106 | 0: "[未指定]", 107 | 1: "ICMP", 108 | 2: "IGMP", 109 | 6: "TCP", 110 | 17: "UDP", 111 | 58: "ICMPV6", 112 | 113: "PGM" 113 | }, 114 | "SocketInfo": { 115 | 0xffffffff: "INVALID_SOCKET [无效套接字]" 116 | } 117 | } 118 | 119 | 120 | def WarningEmit(event, WarningType, WarningID, info, extend=None): 121 | if extend is None: 122 | extend = [] 123 | if WarningType == "Warning" and event['warningLevel'] == 0: 124 | event['warningLevel'] = 1 125 | if WarningType == "Danger": 126 | event['warningLevel'] = 2 127 | event["warnings"].append({ 128 | "WarningID": WarningID, 129 | "type": WarningType, 130 | "info": info, 131 | "extend": extend 132 | }) 133 | 134 | 135 | def to32Hex(number, WhenZero=None): 136 | number &= 0xFFFFFFFF 137 | if WhenZero is not None and number == 0: 138 | return WhenZero 139 | return "0x{:0>8x}".format(number) 140 | 141 | 142 | def toMemorySize(number, Whenzero="0 Bytes"): 143 | number &= 0xFFFFFFFF 144 | if number == 0: 145 | return Whenzero 146 | K = pow(2, 10) 147 | M = pow(2, 20) 148 | if number < K: 149 | return "{} Bytes".format(number) 150 | elif number < M: 151 | return "{:.1f} KB ({:,} Bytes)".format(number / K, number) 152 | else: 153 | return "{:.1f} MB ({:,} Bytes)".format(number / M, number) 154 | 155 | 156 | def convertOr(number, convertDict): 157 | number &= 0xFFFFFFFF 158 | convertList = [to32Hex(number)] 159 | for key in convertDict: 160 | if key & number != 0 or (key == 0 and number % 2 == 0): 161 | convertList.append(convertDict[key]) 162 | if number == 0 and len(convertList) == 0: 163 | return ['无'] 164 | else: 165 | return convertList 166 | 167 | 168 | def convertEqual(number, convertDict): 169 | number &= 0xFFFFFFFF 170 | convertList = [to32Hex(number)] 171 | if number in convertDict: 172 | convertList.append(convertDict[number]) 173 | return convertList 174 | 175 | 176 | # 默认非0为成功,调换请使用reverse 177 | def convertResult(status, reverse=False): 178 | if (not reverse and status == 0) or (reverse and status != 0): 179 | return '失败({})'.format(to32Hex(status)) 180 | else: 181 | return '成功({})'.format(to32Hex(status)) 182 | 183 | 184 | def joinSocketAddr(addr, port): 185 | addr1 = (addr & 0xFF000000) >> 24 186 | addr2 = (addr & 0x00FF0000) >> 16 187 | addr3 = (addr & 0x0000FF00) >> 8 188 | addr4 = (addr & 0x000000FF) 189 | return "{}.{}.{}.{}:{}".format(addr1, addr2, addr3, addr4, port) 190 | 191 | 192 | def formatErrorCode(errorCode): 193 | errorCode &= 0xffffffff 194 | if errorCode == 0: 195 | return "[0] 操作成功。" 196 | return "[{}] {}".format(errorCode, win32api.FormatMessage(errorCode).strip()) 197 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # 软件安全课设 3 | 4 | 已获得2021年度软件安全课程设计作品赛**一等奖** 5 | 6 | ## 系统展示 7 | 8 | ![image](assets/pic1.png) 9 | 10 | ## 捕获的API 11 | 12 | ```C++ 13 | DetourAttach(&(PVOID&)OldMessageBoxA, NewMessageBoxA); 14 | DetourAttach(&(PVOID&)OldHeapCreate, NewHeapCreate); 15 | DetourAttach(&(PVOID&)OldHeapAlloc, NewHeapAlloc); 16 | DetourAttach(&(PVOID&)OldHeapDestroy, NewHeapDestroy); 17 | DetourAttach(&(PVOID&)OldHeapFree, NewHeapFree); 18 | DetourAttach(&(PVOID&)OldCreateFileA, NewCreateFileA); 19 | DetourAttach(&(PVOID&)OldOpenFile, NewOpenFile); 20 | DetourAttach(&(PVOID&)OldReadFile, NewReadFile); 21 | DetourAttach(&(PVOID&)OldWriteFile, NewWriteFile); 22 | DetourAttach(&(PVOID&)_Oldlclose, _Newlclose); 23 | DetourAttach(&(PVOID&)OldCloseHandle, NewCloseHandle); 24 | DetourAttach(&(PVOID&)OldRegCreateKeyExA, NewRegCreateKeyExA); 25 | DetourAttach(&(PVOID&)OldRegOpenKeyExA, NewRegOpenKeyExA); 26 | DetourAttach(&(PVOID&)OldRegQueryValueExA, NewRegQueryValueExA); 27 | DetourAttach(&(PVOID&)OldRegSetValueExA, NewRegSetValueExA); 28 | DetourAttach(&(PVOID&)OldRegCloseKey, NewRegCloseKey); 29 | DetourAttach(&(PVOID&)Oldsocket, Newsocket); 30 | DetourAttach(&(PVOID&)OldWSAStartup, NewWSAStartup); 31 | DetourAttach(&(PVOID&)Oldconnect, Newconnect); 32 | DetourAttach(&(PVOID&)Oldrecv, Newrecv); 33 | DetourAttach(&(PVOID&)Oldsend, Newsend); 34 | DetourAttach(&(PVOID&)Oldclosesocket, Newclosesocket); 35 | DetourAttach(&(PVOID&)OldWSACleanup, NewWSACleanup); 36 | ``` 37 | 38 | 39 | ## 从源文件简要安装方法 40 | 41 | ### 注射器、注入dll文件 42 | 43 | - 下载并编译Detours库,编译使用32位; 44 | - 下载nlohmann_json_realease库, 45 | - 在根目录下建立lib文件夹,复制Detours库和json库的文件夹到这里。 46 | - 编译dll文件,将编译出的dll文件所在目录地址及其自身绝对地址复制到src/Injector/Injector.cpp文件的26/27行相应处 47 | - 编译注射器,将编译出的exe文件绝对地址复制到public/main.py 40行处 48 | 49 | **注:请按照步骤对上述文件编译,若找不到lib文件可以自己手动链接,请使用绝对地址,否则可能会有返回值错误3** 50 | 51 | ### 目标文件 52 | 53 | - 直接使用Visual Studio编译即可,请记住他们的绝对路径。 54 | 55 | ### 网页文件 56 | 57 | - 查看[src/web/README.md](src/web/README.md),按照其指示制作 58 | 59 | ### 运行 60 | 61 | - 用管理员权限运行public/main.py,访问[localhost:9013](http://localhost:9013)即可。注意受到浏览器限制,只能复制文件绝对路径到输入框中 62 | 63 | ## 需要自行下载 64 | 65 | - Detours-4.0.1 66 | - nlohmann_json_release-3.9.1 67 | 68 | 项目中还使用了base64.cpp and base64.h的内容 69 | -------------------------------------------------------------------------------- /src/DetoursDll3/DetoursDll3.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30907.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DetoursDll3", "DetoursDll3.vcxproj", "{DED46DC1-71E7-40C6-BFBB-B8D697461745}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Debug|x64.ActiveCfg = Debug|x64 17 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Debug|x64.Build.0 = Debug|x64 18 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Debug|x86.ActiveCfg = Debug|Win32 19 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Debug|x86.Build.0 = Debug|Win32 20 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Release|x64.ActiveCfg = Release|x64 21 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Release|x64.Build.0 = Release|x64 22 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Release|x86.ActiveCfg = Release|Win32 23 | {DED46DC1-71E7-40C6-BFBB-B8D697461745}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {5E13AF86-AA39-4F02-AD88-F44B8C16DBB2} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/DetoursDll3/DetoursDll3.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 | 16.0 23 | Win32Proj 24 | {ded46dc1-71e7-40c6-bfbb-b8d697461745} 25 | DetoursDll3 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | ..\..\lib\cppcodec-0.2;..\..\lib\nlohmann_json_release-3.9.1;..\..\lib\Detours-4.0.1\include;$(IncludePath) 76 | ..\..\lib\Detours-4.0.1\lib.X86;$(LibraryPath) 77 | 78 | 79 | false 80 | 81 | 82 | true 83 | 84 | 85 | false 86 | 87 | 88 | 89 | Level3 90 | true 91 | WIN32;_DEBUG;DETOURSDLL3_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 92 | true 93 | Use 94 | pch.h 95 | Default 96 | stdc11 97 | 98 | 99 | Windows 100 | true 101 | false 102 | 103 | 104 | 105 | 106 | Level3 107 | true 108 | true 109 | true 110 | WIN32;NDEBUG;DETOURSDLL3_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 111 | true 112 | Use 113 | pch.h 114 | 115 | 116 | Windows 117 | true 118 | true 119 | true 120 | false 121 | 122 | 123 | 124 | 125 | Level3 126 | true 127 | _DEBUG;DETOURSDLL3_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 128 | true 129 | Use 130 | pch.h 131 | 132 | 133 | Windows 134 | true 135 | false 136 | 137 | 138 | 139 | 140 | Level3 141 | true 142 | true 143 | true 144 | NDEBUG;DETOURSDLL3_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 145 | true 146 | Use 147 | pch.h 148 | 149 | 150 | Windows 151 | true 152 | true 153 | true 154 | false 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | Create 166 | Create 167 | Create 168 | Create 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /src/DetoursDll3/DetoursDll3.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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 | -------------------------------------------------------------------------------- /src/DetoursDll3/base64.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/DetoursDll3/base64.h -------------------------------------------------------------------------------- /src/DetoursDll3/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 4 | // Windows 头文件 5 | #include 6 | -------------------------------------------------------------------------------- /src/DetoursDll3/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: 与预编译标头对应的源文件 2 | 3 | #include "pch.h" 4 | 5 | // 当使用预编译的头时,需要使用此源文件,编译才能成功。 6 | -------------------------------------------------------------------------------- /src/DetoursDll3/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: 这是预编译标头文件。 2 | // 下方列出的文件仅编译一次,提高了将来生成的生成性能。 3 | // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 4 | // 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 5 | // 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // 添加要在此处预编译的标头 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /src/Injector/Injector.cpp: -------------------------------------------------------------------------------- 1 | // Injector.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Injector.h" 9 | #pragma comment(lib,"detours.lib") 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | if (argc == 1 || argc > 2) { 14 | return -1; 15 | } 16 | WCHAR EXE[MAX_PATH + 1] = { 0 }; 17 | swprintf_s(EXE, L"%hs", argv[1]); 18 | wprintf(L"%s", EXE); 19 | //std::cout << "Hello World!\n"; 20 | STARTUPINFO si; 21 | PROCESS_INFORMATION pi; 22 | ZeroMemory(&si, sizeof(STARTUPINFO)); 23 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 24 | si.cb = sizeof(STARTUPINFO); 25 | WCHAR DirPath[MAX_PATH + 1]; 26 | wcscpy_s(DirPath, MAX_PATH, L"H:\\softwareSecurityTask\\src\\DetoursDll3\\Debug"); 27 | GetCurrentDirectory(MAX_PATH, DirPath); 28 | char DLLPath[MAX_PATH + 1] = "H:\\softwareSecurityTask\\src\\DetoursDll3\\Debug\\DetoursDll3.dll"; 29 | //char DLLPath[MAX_PATH + 1] = "DetoursDll3.dll"; 30 | 31 | if (DetourCreateProcessWithDllEx(EXE, NULL, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, DirPath, &si, &pi, DLLPath, NULL)) { 32 | printf("Success Hooked!\n"); 33 | ResumeThread(pi.hThread); 34 | WaitForSingleObject(pi.hProcess, INFINITE); 35 | } 36 | else { 37 | return GetLastError(); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /src/Injector/Injector.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/Injector/Injector.h -------------------------------------------------------------------------------- /src/Injector/Injector.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30907.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Injector", "Injector.vcxproj", "{9A909D8D-EAA1-4A07-92D1-C1D12909116D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Debug|x64.ActiveCfg = Debug|x64 17 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Debug|x64.Build.0 = Debug|x64 18 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Debug|x86.Build.0 = Debug|Win32 20 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Release|x64.ActiveCfg = Release|x64 21 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Release|x64.Build.0 = Release|x64 22 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Release|x86.ActiveCfg = Release|Win32 23 | {9A909D8D-EAA1-4A07-92D1-C1D12909116D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {BAD119CD-6427-4840-B741-FA82E81079F9} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/Injector/Injector.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 | 16.0 23 | Win32Proj 24 | {9a909d8d-eaa1-4a07-92d1-c1d12909116d} 25 | Injector 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | ..\..\lib\Detours-4.0.1\include;$(IncludePath) 76 | ..\..\lib\Detours-4.0.1\lib.X86;$(LibraryPath) 77 | 78 | 79 | false 80 | 81 | 82 | true 83 | S:\软件安全设计\Detours-4.0.1\include;$(IncludePath) 84 | S:\软件安全设计\Detours-4.0.1\lib.X64;$(LibraryPath) 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | 96 | 97 | Console 98 | true 99 | RequireAdministrator 100 | 101 | 102 | 103 | 104 | Level3 105 | true 106 | true 107 | true 108 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | true 110 | 111 | 112 | Console 113 | true 114 | true 115 | true 116 | 117 | 118 | 119 | 120 | Level3 121 | true 122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | 125 | 126 | Console 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | true 134 | true 135 | true 136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | true 138 | 139 | 140 | Console 141 | true 142 | true 143 | true 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /src/Injector/Injector.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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 | -------------------------------------------------------------------------------- /src/web/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /src/web/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /src-bex/www 3 | /src-capacitor 4 | /src-cordova 5 | /.quasar 6 | /node_modules 7 | .eslintrc.js 8 | babel.config.js 9 | -------------------------------------------------------------------------------- /src/web/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy 3 | // This option interrupts the configuration hierarchy at this file 4 | // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos) 5 | root: true, 6 | 7 | parserOptions: { 8 | parser: '@babel/eslint-parser', 9 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features 10 | sourceType: 'module' // Allows for the use of imports 11 | }, 12 | 13 | env: { 14 | browser: true 15 | }, 16 | 17 | // Rules order is important, please avoid shuffling them 18 | extends: [ 19 | // Base ESLint recommended rules 20 | // 'eslint:recommended', 21 | 22 | 23 | // Uncomment any of the lines below to choose desired strictness, 24 | // but leave only one uncommented! 25 | // See https://eslint.vuejs.org/rules/#available-rules 26 | 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention) 27 | // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) 28 | // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) 29 | 30 | // https://github.com/prettier/eslint-config-prettier#installation 31 | // usage with Prettier, provided by 'eslint-config-prettier'. 32 | 'prettier' 33 | ], 34 | 35 | plugins: [ 36 | // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-file 37 | // required to lint *.vue files 38 | 'vue', 39 | 40 | // https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674 41 | // Prettier has not been included as plugin to avoid performance impact 42 | // add it as an extension for your IDE 43 | ], 44 | 45 | globals: { 46 | ga: 'readonly', // Google Analytics 47 | cordova: 'readonly', 48 | __statics: 'readonly', 49 | __QUASAR_SSR__: 'readonly', 50 | __QUASAR_SSR_SERVER__: 'readonly', 51 | __QUASAR_SSR_CLIENT__: 'readonly', 52 | __QUASAR_SSR_PWA__: 'readonly', 53 | process: 'readonly', 54 | Capacitor: 'readonly', 55 | chrome: 'readonly' 56 | }, 57 | 58 | // add your custom rules here 59 | rules: { 60 | 'prefer-promise-reject-errors': 'off', 61 | 62 | 63 | // allow debugger during development only 64 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/web/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | plugins: [ 5 | // to edit target browsers: use "browserslist" field in package.json 6 | require('autoprefixer') 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/web/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "octref.vetur" 6 | ], 7 | "unwantedRecommendations": [ 8 | "hookyqr.beautify", 9 | "dbaeumer.jshint", 10 | "ms-vscode.vscode-typescript-tslint-plugin" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/web/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "vetur.validation.template": false, 3 | "vetur.format.enable": false, 4 | "eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"], 5 | 6 | "vetur.experimental.templateInterpolationService": true 7 | } 8 | -------------------------------------------------------------------------------- /src/web/README.md: -------------------------------------------------------------------------------- 1 | # Quasar App (detour) 2 | 3 | A Quasar Framework app 4 | 5 | ## Install the dependencies 6 | ```bash 7 | npm install 8 | ``` 9 | 10 | ### Start the app in development mode (hot-code reloading, error reporting, etc.) 11 | ```bash 12 | quasar dev 13 | ``` 14 | 15 | ### Lint the files 16 | ```bash 17 | npm run lint 18 | ``` 19 | 20 | ### Build the app for production 21 | ```bash 22 | quasar build 23 | ``` 24 | 25 | ### Customize the configuration 26 | See [Configuring quasar.conf.js](https://v2.quasar.dev/quasar-cli/quasar-conf-js). 27 | -------------------------------------------------------------------------------- /src/web/babel.config.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = api => { 4 | return { 5 | presets: [ 6 | [ 7 | '@quasar/babel-preset-app', 8 | api.caller(caller => caller && caller.target === 'node') 9 | ? { targets: { node: 'current' } } 10 | : {} 11 | ] 12 | ] 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/web/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "src/*": [ 6 | "src/*" 7 | ], 8 | "app/*": [ 9 | "*" 10 | ], 11 | "components/*": [ 12 | "src/components/*" 13 | ], 14 | "layouts/*": [ 15 | "src/layouts/*" 16 | ], 17 | "pages/*": [ 18 | "src/pages/*" 19 | ], 20 | "assets/*": [ 21 | "src/assets/*" 22 | ], 23 | "boot/*": [ 24 | "src/boot/*" 25 | ], 26 | "vue$": [ 27 | "node_modules/vue/dist/vue.runtime.esm-bundler.js" 28 | ] 29 | } 30 | }, 31 | "exclude": [ 32 | "dist", 33 | ".quasar", 34 | "node_modules" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /src/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "detour", 3 | "version": "0.0.1", 4 | "description": "A Quasar Framework app", 5 | "productName": "异常行为监测系统", 6 | "author": "6QHTSK <862647431@qq.com>", 7 | "private": true, 8 | "scripts": { 9 | "lint": "eslint --ext .js,.vue ./", 10 | "test": "echo \"No test specified\" && exit 0", 11 | "dev": "quasar dev" 12 | }, 13 | "dependencies": { 14 | "@quasar/extras": "^1.0.0", 15 | "axios": "^0.21.1", 16 | "core-js": "^3.6.5", 17 | "js-base64": "^3.7.1", 18 | "quasar": "^2.0.0", 19 | "socket.io-client": "^4.2.0", 20 | "vue-socket.io": "^3.0.10" 21 | }, 22 | "devDependencies": { 23 | "@babel/eslint-parser": "^7.13.14", 24 | "@quasar/app": "^3.0.0", 25 | "electron": "^15.0.0", 26 | "electron-packager": "^15.4.0", 27 | "eslint": "^7.14.0", 28 | "eslint-config-prettier": "^8.1.0", 29 | "eslint-plugin-vue": "^7.0.0", 30 | "eslint-webpack-plugin": "^2.4.0" 31 | }, 32 | "browserslist": [ 33 | "last 10 Chrome versions", 34 | "last 10 Firefox versions", 35 | "last 4 Edge versions", 36 | "last 7 Safari versions", 37 | "last 8 Android versions", 38 | "last 8 ChromeAndroid versions", 39 | "last 8 FirefoxAndroid versions", 40 | "last 10 iOS versions", 41 | "last 5 Opera versions" 42 | ], 43 | "engines": { 44 | "node": ">= 12.22.1", 45 | "npm": ">= 6.13.4", 46 | "yarn": ">= 1.21.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/public/favicon.ico -------------------------------------------------------------------------------- /src/web/public/icons/favicon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/public/icons/favicon-128x128.png -------------------------------------------------------------------------------- /src/web/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /src/web/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /src/web/public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /src/web/quasar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/quasar -------------------------------------------------------------------------------- /src/web/quasar.conf.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file runs in a Node context (it's NOT transpiled by Babel), so use only 3 | * the ES6 features that are supported by your Node version. https://node.green/ 4 | */ 5 | 6 | // Configuration for your app 7 | // https://v2.quasar.dev/quasar-cli/quasar-conf-js 8 | 9 | /* eslint-env node */ 10 | const ESLintPlugin = require('eslint-webpack-plugin') 11 | const { configure } = require('quasar/wrappers'); 12 | 13 | module.exports = configure(function (ctx) { 14 | return { 15 | // https://v2.quasar.dev/quasar-cli/supporting-ts 16 | supportTS: false, 17 | 18 | // https://v2.quasar.dev/quasar-cli/prefetch-feature 19 | // preFetch: true, 20 | 21 | // app boot file (/src/boot) 22 | // --> boot files are part of "main.js" 23 | // https://v2.quasar.dev/quasar-cli/boot-files 24 | boot: [ 25 | 'axios', 26 | 'socketio' 27 | ], 28 | 29 | // https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css 30 | css: [ 31 | 'app.scss' 32 | ], 33 | 34 | // https://github.com/quasarframework/quasar/tree/dev/extras 35 | extras: [ 36 | // 'ionicons-v4', 37 | // 'mdi-v5', 38 | // 'fontawesome-v5', 39 | // 'eva-icons', 40 | // 'themify', 41 | // 'line-awesome', 42 | // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! 43 | 44 | 'roboto-font', // optional, you are not bound to it 45 | 'material-icons', // optional, you are not bound to it 46 | ], 47 | 48 | // Full list of options: https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build 49 | build: { 50 | vueRouterMode: 'hash', // available values: 'hash', 'history' 51 | 52 | // transpile: false, 53 | 54 | // Add dependencies for transpiling with Babel (Array of string/regex) 55 | // (from node_modules, which are by default not transpiled). 56 | // Applies only if "transpile" is set to true. 57 | // transpileDependencies: [], 58 | 59 | // rtl: true, // https://v2.quasar.dev/options/rtl-support 60 | // preloadChunks: true, 61 | // showProgress: false, 62 | // gzip: true, 63 | // analyze: true, 64 | 65 | // Options below are automatically set depending on the env, set them if you want to override 66 | // extractCSS: false, 67 | 68 | // https://v2.quasar.dev/quasar-cli/handling-webpack 69 | // "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain 70 | chainWebpack (chain) { 71 | chain.plugin('eslint-webpack-plugin') 72 | .use(ESLintPlugin, [{ extensions: [ 'js', 'vue' ] }]) 73 | }, 74 | }, 75 | 76 | // Full list of options: https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-devServer 77 | devServer: { 78 | https: false, 79 | port: 8080, 80 | open: true // opens browser window automatically 81 | }, 82 | 83 | // https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-framework 84 | framework: { 85 | config: {}, 86 | 87 | // iconSet: 'material-icons', // Quasar icon set 88 | // lang: 'en-US', // Quasar language pack 89 | 90 | // For special cases outside of where the auto-import strategy can have an impact 91 | // (like functional components as one of the examples), 92 | // you can manually specify Quasar components/directives to be available everywhere: 93 | // 94 | // components: [], 95 | // directives: [], 96 | 97 | // Quasar plugins 98 | plugins: [ 99 | 'Notify' 100 | ] 101 | }, 102 | 103 | // animations: 'all', // --- includes all animations 104 | // https://v2.quasar.dev/options/animations 105 | animations: 'all', 106 | 107 | // https://v2.quasar.dev/quasar-cli/developing-ssr/configuring-ssr 108 | ssr: { 109 | pwa: false, 110 | 111 | // manualStoreHydration: true, 112 | // manualPostHydrationTrigger: true, 113 | 114 | prodPort: 3000, // The default port that the production server should use 115 | // (gets superseded if process.env.PORT is specified at runtime) 116 | 117 | maxAge: 1000 * 60 * 60 * 24 * 30, 118 | // Tell browser when a file from the server should expire from cache (in ms) 119 | 120 | chainWebpackWebserver (chain) { 121 | chain.plugin('eslint-webpack-plugin') 122 | .use(ESLintPlugin, [{ extensions: [ 'js' ] }]) 123 | }, 124 | 125 | middlewares: [ 126 | ctx.prod ? 'compression' : '', 127 | 'render' // keep this as last one 128 | ] 129 | }, 130 | 131 | // https://v2.quasar.dev/quasar-cli/developing-pwa/configuring-pwa 132 | pwa: { 133 | workboxPluginMode: 'GenerateSW', // 'GenerateSW' or 'InjectManifest' 134 | workboxOptions: {}, // only for GenerateSW 135 | 136 | // for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts]) 137 | // if using workbox in InjectManifest mode 138 | chainWebpackCustomSW (chain) { 139 | chain.plugin('eslint-webpack-plugin') 140 | .use(ESLintPlugin, [{ extensions: [ 'js' ] }]) 141 | }, 142 | 143 | manifest: { 144 | name: `异常行为监测系统`, 145 | short_name: `Quasar App`, 146 | description: `A Quasar Framework app`, 147 | display: 'standalone', 148 | orientation: 'portrait', 149 | background_color: '#ffffff', 150 | theme_color: '#027be3', 151 | icons: [ 152 | { 153 | src: 'icons/icon-128x128.png', 154 | sizes: '128x128', 155 | type: 'image/png' 156 | }, 157 | { 158 | src: 'icons/icon-192x192.png', 159 | sizes: '192x192', 160 | type: 'image/png' 161 | }, 162 | { 163 | src: 'icons/icon-256x256.png', 164 | sizes: '256x256', 165 | type: 'image/png' 166 | }, 167 | { 168 | src: 'icons/icon-384x384.png', 169 | sizes: '384x384', 170 | type: 'image/png' 171 | }, 172 | { 173 | src: 'icons/icon-512x512.png', 174 | sizes: '512x512', 175 | type: 'image/png' 176 | } 177 | ] 178 | } 179 | }, 180 | 181 | // Full list of options: https://v2.quasar.dev/quasar-cli/developing-cordova-apps/configuring-cordova 182 | cordova: { 183 | // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing 184 | }, 185 | 186 | // Full list of options: https://v2.quasar.dev/quasar-cli/developing-capacitor-apps/configuring-capacitor 187 | capacitor: { 188 | hideSplashscreen: true 189 | }, 190 | 191 | // Full list of options: https://v2.quasar.dev/quasar-cli/developing-electron-apps/configuring-electron 192 | electron: { 193 | bundler: 'packager', // 'packager' or 'builder' 194 | 195 | packager: { 196 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options 197 | 198 | // OS X / Mac App Store 199 | // appBundleId: '', 200 | // appCategoryType: '', 201 | // osxSign: '', 202 | // protocol: 'myapp://path', 203 | 204 | // Windows only 205 | // win32metadata: { ... } 206 | }, 207 | 208 | builder: { 209 | // https://www.electron.build/configuration/configuration 210 | 211 | appId: 'detour' 212 | }, 213 | 214 | // "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain 215 | chainWebpackMain (chain) { 216 | chain.plugin('eslint-webpack-plugin') 217 | .use(ESLintPlugin, [{ extensions: [ 'js' ] }]) 218 | }, 219 | 220 | // "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain 221 | chainWebpackPreload (chain) { 222 | chain.plugin('eslint-webpack-plugin') 223 | .use(ESLintPlugin, [{ extensions: [ 'js' ] }]) 224 | }, 225 | } 226 | } 227 | }); 228 | -------------------------------------------------------------------------------- /src/web/src-electron/electron-main.js: -------------------------------------------------------------------------------- 1 | import { app, BrowserWindow, nativeTheme } from 'electron' 2 | import path from 'path' 3 | 4 | try { 5 | if (process.platform === 'win32' && nativeTheme.shouldUseDarkColors === true) { 6 | require('fs').unlinkSync(require('path').join(app.getPath('userData'), 'DevTools Extensions')) 7 | } 8 | } catch (_) { } 9 | 10 | let mainWindow 11 | 12 | function createWindow () { 13 | /** 14 | * Initial window options 15 | */ 16 | mainWindow = new BrowserWindow({ 17 | width: 1000, 18 | height: 600, 19 | useContentSize: true, 20 | webPreferences: { 21 | contextIsolation: true, 22 | // More info: /quasar-cli/developing-electron-apps/electron-preload-script 23 | preload: path.resolve(__dirname, process.env.QUASAR_ELECTRON_PRELOAD) 24 | } 25 | }) 26 | 27 | mainWindow.loadURL(process.env.APP_URL) 28 | 29 | if (process.env.DEBUGGING) { 30 | // if on DEV or Production with debug enabled 31 | mainWindow.webContents.openDevTools() 32 | } else { 33 | // we're on production; no access to devtools pls 34 | mainWindow.webContents.on('devtools-opened', () => { 35 | mainWindow.webContents.closeDevTools() 36 | }) 37 | } 38 | 39 | mainWindow.on('closed', () => { 40 | mainWindow = null 41 | }) 42 | } 43 | 44 | app.on('ready', createWindow) 45 | 46 | app.on('window-all-closed', () => { 47 | if (process.platform !== 'darwin') { 48 | app.quit() 49 | } 50 | }) 51 | 52 | app.on('activate', () => { 53 | if (mainWindow === null) { 54 | createWindow() 55 | } 56 | }) 57 | -------------------------------------------------------------------------------- /src/web/src-electron/electron-preload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used specifically for security reasons. 3 | * Here you can access Nodejs stuff and inject functionality into 4 | * the renderer thread (accessible there through the "window" object) 5 | * 6 | * WARNING! 7 | * If you import anything from node_modules, then make sure that the package is specified 8 | * in package.json > dependencies and NOT in devDependencies 9 | * 10 | * Example (injects window.myAPI.doAThing() into renderer thread): 11 | * 12 | * import { contextBridge } from 'electron' 13 | * 14 | * contextBridge.exposeInMainWorld('myAPI', { 15 | * doAThing: () => {} 16 | * }) 17 | */ 18 | -------------------------------------------------------------------------------- /src/web/src-electron/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/src-electron/icons/icon.icns -------------------------------------------------------------------------------- /src/web/src-electron/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/src-electron/icons/icon.ico -------------------------------------------------------------------------------- /src/web/src-electron/icons/linux-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/src-electron/icons/linux-512x512.png -------------------------------------------------------------------------------- /src/web/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 11 | -------------------------------------------------------------------------------- /src/web/src/assets/quasar-logo-vertical.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /src/web/src/boot/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/6QHTSK/SoftwareSecurityTask/b2d41ee4a867aa37f1e4df34870dfdad73638aa3/src/web/src/boot/.gitkeep -------------------------------------------------------------------------------- /src/web/src/boot/axios.js: -------------------------------------------------------------------------------- 1 | import { boot } from 'quasar/wrappers' 2 | import axios from 'axios' 3 | 4 | // Be careful when using SSR for cross-request state pollution 5 | // due to creating a Singleton instance here; 6 | // If any client changes this (global) instance, it might be a 7 | // good idea to move this instance creation inside of the 8 | // "export default () => {}" function below (which runs individually 9 | // for each client) 10 | const api = axios.create({ baseURL: 'https://api.example.com' }) 11 | 12 | export default boot(({ app }) => { 13 | // for use inside Vue files (Options API) through this.$axios and this.$api 14 | 15 | app.config.globalProperties.$axios = axios 16 | // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) 17 | // so you won't necessarily have to import axios in each vue file 18 | 19 | app.config.globalProperties.$api = api 20 | // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) 21 | // so you can easily perform requests against your app's API 22 | }) 23 | 24 | export { api } 25 | -------------------------------------------------------------------------------- /src/web/src/boot/socketio.js: -------------------------------------------------------------------------------- 1 | import { boot } from 'quasar/wrappers' 2 | // import VueSocketIO from "vue-socket.io"; 3 | import io from 'socket.io-client' 4 | 5 | 6 | // "async" is optional; 7 | // more info on params: https://v2.quasar.dev/quasar-cli/boot-files 8 | export default boot(async ({ app }) => { 9 | app.config.globalProperties.$socketIO = null 10 | app.config.globalProperties.$socketIO = await io('http://localhost:9013') 11 | }) 12 | 13 | export {io} 14 | -------------------------------------------------------------------------------- /src/web/src/components/EssentialLink.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 52 | -------------------------------------------------------------------------------- /src/web/src/css/app.scss: -------------------------------------------------------------------------------- 1 | // app global css in SCSS form 2 | -------------------------------------------------------------------------------- /src/web/src/css/quasar.variables.scss: -------------------------------------------------------------------------------- 1 | // Quasar SCSS (& Sass) Variables 2 | // -------------------------------------------------- 3 | // To customize the look and feel of this app, you can override 4 | // the Sass/SCSS variables found in Quasar's source Sass/SCSS files. 5 | 6 | // Check documentation for full list of Quasar variables 7 | 8 | // Your own variables (that are declared here) and Quasar's own 9 | // ones will be available out of the box in your .vue/.scss/.sass files 10 | 11 | // It's highly recommended to change the default colors 12 | // to match your app's branding. 13 | // Tip: Use the "Theme Builder" on Quasar's documentation website. 14 | 15 | $primary : #1976D2; 16 | $secondary : #26A69A; 17 | $accent : #9C27B0; 18 | 19 | $dark : #1D1D1D; 20 | 21 | $positive : #21BA45; 22 | $negative : #C10015; 23 | $info : #31CCEC; 24 | $warning : #F2C037; 25 | -------------------------------------------------------------------------------- /src/web/src/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/web/src/layouts/MainLayout.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 114 | -------------------------------------------------------------------------------- /src/web/src/pages/Error404.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 32 | -------------------------------------------------------------------------------- /src/web/src/pages/Index.vue: -------------------------------------------------------------------------------- 1 | 237 | 238 | 567 | 568 | 606 | -------------------------------------------------------------------------------- /src/web/src/pages/descriptionGenerator.js: -------------------------------------------------------------------------------- 1 | function generator(event){ 2 | 3 | } 4 | export { generator } 5 | -------------------------------------------------------------------------------- /src/web/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { route } from 'quasar/wrappers' 2 | import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router' 3 | import routes from './routes' 4 | 5 | /* 6 | * If not building with SSR mode, you can 7 | * directly export the Router instantiation; 8 | * 9 | * The function below can be async too; either use 10 | * async/await or return a Promise which resolves 11 | * with the Router instance. 12 | */ 13 | 14 | export default route(function (/* { store, ssrContext } */) { 15 | const createHistory = process.env.SERVER 16 | ? createMemoryHistory 17 | : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory) 18 | 19 | const Router = createRouter({ 20 | scrollBehavior: () => ({ left: 0, top: 0 }), 21 | routes, 22 | 23 | // Leave this as is and make changes in quasar.conf.js instead! 24 | // quasar.conf.js -> build -> vueRouterMode 25 | // quasar.conf.js -> build -> publicPath 26 | history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE) 27 | }) 28 | 29 | return Router 30 | }) 31 | -------------------------------------------------------------------------------- /src/web/src/router/routes.js: -------------------------------------------------------------------------------- 1 | 2 | const routes = [ 3 | { 4 | path: '/', 5 | component: () => import('layouts/MainLayout.vue'), 6 | children: [ 7 | { path: '', component: () => import('pages/Index.vue') } 8 | ] 9 | }, 10 | 11 | // Always leave this as last one, 12 | // but you can also remove it 13 | { 14 | path: '/:catchAll(.*)*', 15 | component: () => import('pages/Error404.vue') 16 | } 17 | ] 18 | 19 | export default routes 20 | -------------------------------------------------------------------------------- /test/HeapFreeTwice/.idea/HeapFreeTwice.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/HeapFreeTwice/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/HeapFreeTwice/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/HeapFreeTwice/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |