参考系列:https://blog.csdn.net/billvsme/article/details/38305839
请合法使用,本教程只是汇总上面的方法。
界面
快捷键
F3 : 打开目标文件
F2 : 设置断点
F7:单步步进,遇到CALL跟进
F8:单步步过,遇到CALL路过,不跟进
F9:运行调试程序,直到运行到断点处
F4:运行调试程序,直到运行到光标处
Ctrl+F7/F8 相当于一直按F7/F8
Ctrl+F9 快速跳出函数
Alt+F9 快速跳出系统函数
Ctrl+F2 重新载入程序
**在反汇编面板中**
;键:写注解
空格键:改变当前的指令
**在数据面板中**
Ctrl+G:打开地址窗口
空格:编辑数据
实战1:修改数据
1、按住F8直到找到位置(弹出一个MessageBox窗口)
2、再次,进入到位置里,找到要改的值
3、修改值(根据数据地址,到数据面板 按下Ctrl+G 输入 地址 鼠标选中要改的地方,按下空格键输入要改动字符。)
4、永久保存(选中改过的部分–>右键选择复制到可执行程序–>备份–>保存数据到文件)
在OllyDbg中按F3打开hello.exe
按住F8 直到弹出hello窗口
单步运行到004010E9时会停下来,弹出一个MessageBox窗口。
在这里下一个断点。
再按Ctrl+F2重新载入,再按F9运行到断点处。在F7步进,进入函数中。
我们可以看到
可以看到4个PUSH和一个CALL
四个PUSH就相当于参数。可以看到右边的注解(OllDbg会根据dll自动注解),这其实是MessageBox的4个参数,由于VC++默认函数是__stdcall 所以参数进栈的顺序是从右往左的。
我们可以看到MessageBox显示的窗口和内容的字符串的地址。通过修改相应地址的内容就可以改变窗口的内容。
在数据面板 按下Ctrl+G s 输入 00406030 (参数值Welcome)
鼠标选中要改的地方,按下空格键输入要改动字符。
由于是调用MessageBoxA(A代表ASCII),所以在ASCII中输入想要字符,记得要以00结尾。例如输入 “哈哈!!”
这样修改在重新载入后就会失效。如果想保存到应用程序
选中改过的部分,右键选择复制到可执行程序
在弹出的窗口中右键选择 备份-->保存数据到文件即可
实战2:修改代码
1、把关键部分(跳转等)选中,按下空格键输入nop
但我们输入的是错误的时候,我们可以发现这个地方 je 是跳转的,我们可以通过在右边修改标志寄存器(点击Z 后面的1)让je不跳转 或者直接把 je short 0040122E改成 nop(选中,按下空格键输入nop),进行暴力处理。
实战:2.1:获取正确序列号,重要数据等
1、输入一个错误的,程序会比如cmp比较,就能看到正确的值。
我们可以发现call dword ptr [<&KERNEL32.lstrcmp>; lstrcmp指令,说明前面的两参数一定是用来比较的,一个是自己写的错误序列号,一个是这个函数计算出来的正确的序列号。
按F8运行到call dword ptr [<&KERNEL32.lstrcmp>; 处,我们可以发现ebp存放的是“6854”字符串的地址,eax就是我们写的字符串“12345678”的地址(输入的用户名为billvsme,序列号为12345678)。从而我们就可以只到用户名“billvsme”的序列号为6854。
实战3:跳过关键验证
程序会从一个地方读出注册的信息,比如注册表,文件,数据库等。先监听这些windows api接口能快速定位关键地方。
我们先把0040107B 的 jnz short 0040109A改成 jmp short004010D8即可。直接跳过。
实战4:解决OD卡死 (PE文件被故意修改)
1、先到 选项—> 调试设置 --> 事件 --> 选择系统断点。这样用OD打开就不会卡死。
2、修改一些异常值后,再改回 WinMAin
https://blog.csdn.net/billvsme/article/details/38340937
实战4.1:去弹窗
1、直接把弹出窗口的全代码改成nop。方法是选中代码,右键–>二进制–>用nop填充。
或 看MessageBox的函数说明,第一个参数hWnd,表示MessageBox的父窗口。把这个参数改成一个非法的句柄,让MessageBox运行出错。push 0 改成 push 1,MessageBox就不会显示了。
实战5: 去除数量限制
当提示你超出数量时,找到位置,跳过去。
可以发现 jl short 00412DEF 很关键,如果他跳转了,就不会弹出ERROR窗口 。
把jl short 00412DEF 改成 jmp short 00412DEF 保存,再运行添加联络人的限制就没了。
实战5.1:忽略OD异常
选项–>调试设置–>选择异常–>在同时忽略以下指定的异常或范围,并且点击添加范围,写入00000000~FFFFFFFF
实战5.2:修改字符串
用OD打开程序,右键–>查找–>所有参考文本字串,双击找到的文本到代码处。
对程序标题和About中的UNREGISERED 修改:
直接在CPU窗口的数据面版,按Ctrl+B,输入相应的字符串查找(有ASCII与UNCODE,如果找不到两个都试试)。
找到后直接修改保存。
实战6:去广告窗口
1、F8运行程序,碰到出现窗口的CALL就下断点,重新运行按F7进入此CALL,观察此CALL前后的代码。改返回值或关键地方改成nop。
可以发现这个CALL返回eax=1,而且下面的一句是判断cmp是否是1,是1就正常运行。所以这个CALL的作用就是调用窗口,把使用次数减1,返回是否要正常运行。
所以,只需把call <jmp.&MFC42.#2514_CDialog::DoModal>改成 mov eax,1 即可实现去除NAG窗口跟使用次数限制。
方法二:
程序注册前(或者说不能正常使用)与注册后(或者说能正常使用)。代码的走到过程肯定是不一样的。要么是 jl,jnz等跳不跳转,要么是jmp 寄存器 中 寄存器的值不一样。所以,我们只需F8运行程序,记录下每次jl,jnz等跳不跳,然后多运行几次程序,用完剩余的使用次数,再在OD中F8运行程序,观察下每次jl,jnz等跳不跳,与之前正常运行的做对比,一定发现不一样的就要仔细分析。
方法三: 直接把call <jmp.&MFC42.#2514_CDialog::DoModal>改成nop,即可去除广告窗口。
实战7:根据字符串跳过关键验证
用OD打开程序,右键–>查找–>所有参考文本字串,双击找到的文本到代码处。定位到验证失败,向上找判断。改判断结果跳转到正确分支。
把第一个cmp byte ptr [eax], 0 改成 cmp byte ptr [eax], 1 使跳转实现。
按照同样的方法,搜索<Unregistered Version>,跟改跳转实现,即可跳过关键验证程序。
实战7.1:改试用期
要找出改[[60EB8C]]的值的地方。
选中mov eax, dword ptr [60EB8C] , 右键-->查找参考-->地址常量,即可列出所有使用了这个地址的命令的位置。
在此窗口右键-->在每个命令上设置断点。重新运行程序。
看到 mov byte ptr [edx], al 正是给[[60EB8C]] 赋值的地方,把它改成 mov byte ptr [edx], 1,值写死。
(在保存过程中会出现 重定位提示窗口,因为mov byte ptr [edx], al改成mov byte ptr [edx], 1后代码变多了,要重定位才可能正常运行。这里可以先不用管它。)
实战8:解锁限制的功能
深入的找到关键的控制功能的点。
https://blog.csdn.net/billvsme/article/details/38736579
实战9:VB写的
用PEiD来查看这个程序的类型,可以发现这个程序使用VB写的。
VB可以走捷径。可以直接等对 用来比较API函数 下断点来调试。
关键的 用来比较的API函数:
变量比较:
__vbaVarTstEq
__vbaVarCompEq
__vbaVarCompLe
__vbaVarCompLt
__vbaVarCompGe
__vbaVarCompGt
__vbaVarCompNe
字符串比较:
__vbaStrCmp
__vbaStrComp
__vbaStrCompVar
__vbaStrLike
__vbaStrTextComp
__vbaStrTextLike
加载程序。按 ctrl+N 查看输入输入出表
直接输入vbavartsteq (直接在这个窗口上输入,窗口标题栏可以显示已输入的内容),
可以看到__vbaVarTstEq,选中它,右键-->在每个参考上设置断点。可以发现设置了88个断点
回到cpu面板,先按F9,运行到断点处,在按F8单步调试。
运行到此处,可以发现005BBFD9 一串很想注册码的字符串。
运行程序,直接输入这个字符串,尝试正常,可以发现注册成功。
实战10:解锁限制的功能 另一示例
https://blog.csdn.net/billvsme/article/details/38854061
实战11: 跳过关键验证 注册 另一示例
dephi也行
https://blog.csdn.net/billvsme/article/details/38870809
实战12: 跳过关键验证 注册 另一示例
解决提示已经注册但实际没注册。
先从输入的API入手试试。
右键-->查找-->所有模块间的调用,搜索GetWindowTextA (直接输入这些字母即可搜索),选中找到的的调用,右键-->“在每个调用到GetWindowTextA设置断点”。 我们可以查看OD设置了3个断点。(我们也可以按Ctrl+N查看输入输出表搜索GetWindowTextA设置断点)。
按F9运行程序,在程序还没有运行到现实接面时,前面两个断点就触发了,而且触发了好多次。可以知道前面的2个都与About界面的输入无关,取消这两个断点。重新运行程序,在About中的Registration中输入name和key,点击OK,可以发现程序断在了第3个断点上。
按F8单步运行程序,运行到下面代码处
我们可以发现 jnz short 004174E3 很关键它的跳转决定了后面输出窗口是"Invalid code." 还是 "Congratulations! successfully registered" ,但是如果我们只是把它改成jmp short 004174E3 虽然会弹出注册成功的窗口,但实际上还是没有注册。我们可以看看它前面的call 00417690。
重新运行程序,进入00417690。我们可以查看00417690 函数,可以发现这个函数有两处返回,第一处返回前,函数使得al变为1, 第二处返回前,函数使得al变为0。按F8,单步运行程序,改变标志寄存器或者指令使得00417690 函数在第一处retn 返回。但是这样实现了以后依然是会弹出注册成功的窗口,但实际上还是没有注册。
我们可以尝试别的方法进行处理。冲关键的字符串入手。
我们可以重About界面中的“This XoftSpy license has not been registered” 入手,搜索次字符串,查看代码所在的位置
在0040147D处下断点,重新运行程序,可以发现当按下主界面的About按钮时,就会中断在0040147D处。尝试直接把 je short 004014AD 改成 nop,可以发现程序就被注册了。
实战13: 内嵌补丁
方法一:内嵌补丁
方法二: 查看调用堆栈 (暂停程序,按 alt+K 查看堆栈调用,看call 在这个call上下断点,重新运行程序)
可以发现真是这个call产生了nag窗口。
查找这段代码的开头(即找push ebp)
在push ebp 下断点重新运行程序,按F9运行,来到断点处。
按F8单步运行,变按边注意跳转,改变寄存器 ,使程序跳过call 005ABE4D。
可以发现只要使 jnz short 004DBDE6 不跳转即可以实现跳过call 005ABE4D。
实战14:去弹窗 另一示例 内嵌补丁
用OD加载这个程序,按F9运行,当第一个nag窗口出现时,按下暂停。查看 堆栈调用
观察这些调用,查找产生这个nag窗口的调用,此程序是用VC6.0++写的,使用MFC,可以发现此次dialog非常关键
点击它的“调用来自” 可以看到下面代码
只要第一次跟第三次让程序跳过0042039A处的call <jmp.&MFC42.#2514_CDialog::DoMod>,让第二次运行0042039A处的call <jmp.&MFC42.#2514_CDialog::DoMod>
这就需要修改一段代码,
我们可以用内嵌补丁,可以在程序代码最后面找到一片空白的区域,例如这里就用00437D70。
先把je short 004203BA 改成 jmp 00437D70 ,由于原来的代码只占2个字节,改后的代码占用5个字节,lea ecx, dword ptr [esp+4C] 会被覆盖。 在00437D70敲入代码,因为敲 的代码表多,一行一行的改没有效率,可以用NonaWrite这个插件来写代码(下载地址:http://tools.pediy.com/Debuggers/ollydbg/ollydbg1/plugin/NonaWrite/NonaWrite1.2.rar,下载后,直接解压到od目录下的plugin文件夹中),打开插件,敲入
点击Assemble再点击Done(不要忘记点Done,否则运行会有问题),保存修改,即可完成处理。代码中[445EE0]被当做一个变量,相当于 i ,445EE0 这个地址是随便选的,只要是程序的数据区中空白的切不会再运行中用到的地方即可。按alt+M从内存映射表中点击 .data 即可查看数据区,在数据区后面的地方,就可以看到大片空白的地方。如果不缺定空白的地方是否会在程序运行时被使用,只要在想要用的地方下硬件写入断点,运行程序观察是否被断下即可。
实战15: 跳过关键验证 注册 另一示例
通过对话框的hinstance
win32中对话框分模态对话框与非模态对话框,
模态对话框用int DialogBoxParam(HINSTANCE hInstance,LPCTSTR IpTemplateName,HWND hWndParent, DLGPROC IPDialogFunc,LPARAM dwlnitParam);来创建。
非模态对话框用HWND CreateDialogParam(HINSTANCE hlnstancem,LPCTSTR IpTemplateName,HWND hWndParent,DLGPROCIpDialogFunc, LPARAM dwlniParam);来创建
我们可以通过搜索创建对话框函数要传入的hInstance参数来处理,即搜索 push hInstance。
此程序,运行结束后会差生nag窗口,既然nag窗口是对话框肯定有他的hinstance,通过exescope查看nag窗口的hinstance
查找调用此处的代码的方法
因为call xxx 肯定会保存当前的代码的地址,所以,只需运行到断点处,观察堆栈窗口即可。
按F9运行,再关闭程序的窗口,即可到此处。
查看堆栈窗口:
方法一:可以发现绿色框框中即是
绿色方框内即是 调用此处代码的call的后一个命令的地址。
选中它,选中 右键–>反汇编窗口中跟随,即可来到调用此处代码的call。
方法二:观察push 0x67 前面的代码,找到这个函数函数头(关键找nop 和 push ebp)
选中函开始的代码 push ebp,右键–> 查找参考–>选中命令,即可看到调用这个函数的call。
实战16: 跳过tag窗口 另一示例
此程序运行进行后有一个nag窗口,可以从这个nag窗口人手,用Resource Hacker这个软件查找这个nag的hInstance
可以知道这个nag窗口的hInstance为100(十进制),把程序加载到OD,搜索push 0x64
再所有push 0x64上下断点。运行程序,找到是产生nag窗口的那个call。删除其它断点。观察这个call 的前面的代码,可以发 je short 0040672E 可以跳过这个call,而决定这个 je 跳不跳的是 call 00431650
在 call 00431650上面下断点,重新运行程序,进入call 00431650,查看代码
可以发现这个函数是用来读取注册表中的name和key来通过call 00431590来判断name和key是否正确。
我们可以在函数结尾的mov eax, ebx 改成 mov al,1 来处理 (不可以改成mov eax,1因为mov eax,1占用5个字节,改后会覆盖后面的代码)
实战17:从输入框定位
可以从两个输入栏入手,用OD加载程序,右键–>查找–>所以摸快间的调用,搜索跟输入框的API,可以搜索GetDlgItemTextA
(也可以在Commod中输入 bp GetDlgItemTextA 即可直接对指定API下断点)
实战18:程序自身被加密
有点复杂了
https://blog.csdn.net/billvsme/article/details/39135481
实战19:程序对OD反调试
它们自己运行时都没有问题,都显示被注册信息 “You really did it! Congratz it",但是一到OD中运行就会出现未注册或者报错。
它们都用了IsDebuggerPresent这个API函数来判断是否程序被调试器调用。
函数通过IsDebuggerPresent这个API判断是否使用OD调式程序,如果是eax = 1,je short 004010E2 实现跳转,产生”Keyfile is not valid.Sorry.“窗口。可以直接把je short 004010E2 改成nop 就可以去除反调试。其它三个ReverseMe都大同小异。
**另一种:**可以发现call 004011CB其实是查看当前系统所有的进程,搜索所有进程中的是否存在叫“OLLYDBG.EXE”的进程,如果有就产生ERROR窗口。
您提交的内容是“Either of the flows below will be chosen based on the keyStatus”,这是一个说明性的句子,用于描述决策过程或条件逻辑。下面是对这个句子的详细分析:
-
翻译为中文:根据keyStatus的状态,将选择以下流程中的任何一个。
-
时态与语法分析:这个句子使用了一般将来时,表示将来会基于某个条件(keyStatus的状态)来做出选择。句子的语法是正确的。
-
句子结构分析:
- “Either of the flows” 是主语,指的是两个或多个流程中的任何一个。这里使用 “Either” 强调从多个选项中选择一个。
- “below” 是副词,用来修饰 “the flows”,指的是紧接着本句之后提到的流程。
- “will be chosen” 是谓语,使用了被动语态,表示主语 “Either of the flows” 是被选择的对象。这里使用一般将来时的被动语态。
- “based on” 是介词短语,用来说明选择的依据。
- “the keyStatus” 是名词短语,作为 “based on” 的宾语,说明决策是基于 “keyStatus” 的状态。
-
相似的英文例句:
- “The method to be applied depends on the circumstances.”
翻译:将应用的方法取决于具体情况。 - “The decision will be made according to the guidelines.”
翻译:决定将根据指导方针做出。 - “One of the options will be selected based on the criteria.”
翻译:将根据标准选择选项中的一个。
- “The method to be applied depends on the circumstances.”
chosen 是choose的过去分词
您提交的内容是“Intentional blank space to improve readability”,但它本身并不是一个完整的句子,而是一种说明或描述。不过,我会按照您的要求来分析。
-
翻译为中文:有意留下空白处以提高可读性。
-
时态与语法分析:这个表述没有动词,所以没有特定的时态。从语法角度来看,这个表述是正确的,它是一个说明性的短语,用于描述某种行为或目的。
-
句子结构分析:
- “Intentional” 是形容词,修饰后面的名词 “blank space”,表示空白处是故意留下的。
- “blank space” 是名词短语,作为主语,指被故意留下的空白区域。
- “to improve” 是不定式,表示目的,说明为什么要留下这个空白处。
- “readability” 是名词,作为不定式 “to improve” 的宾语,表示提高的是可读性。
-
相似的英文例句:
- “Extra spacing between paragraphs to enhance clarity.”
翻译:段落之间额外增加空格以增强清晰度。 - “Carefully structured layout to facilitate understanding.”
翻译:精心构造的布局以促进理解。 - “Use of bullet points to simplify presentation.”
翻译:使用项目符号简化演示。
- “Extra spacing between paragraphs to enhance clarity.”