本帖最后由 var 于 2018-5-8 11:19 编辑
上一篇地址:https://www.52pojie.cn/thread-648175-1-1.html
讲述了 如何暴力删除未注册的字样,但是这样的做法不符合装逼者的心态,本文讲解,怎么修改内存的关键区域,让程序实现自我注册
如果不想破解,注册码
—– BEGIN LICENSE —–
TwitterInc
200 User License
EA7E-890007
1D77F72E 390CDD93 4DCBA022 FAF60790
61AA12C0 A37081C5 D0316412 4584D136
94D7F7D4 95BC8C1C 527DA828 560BB037
D1EDDD8C AE7B379F 50C9D69D B35179EF
2FE898C4 8E4277A8 555CE714 E1FB0E43
D5D52613 C3D12E98 BC49967F 7652EED2
9D2D2E61 67610860 6D338B72 5CF95C69
E36B85CC 84991F19 7575D828 470A92AB
—— END LICENSE ——
在观看本文之前,一定要看一下上文的内容,本文不需要暴力,仅仅需要修改一段简单的代码。
注意:你并不需要修改上一篇的任何代码,这篇是全新的修改方法。
1. 通过上篇文我们知道 About 页面中有一段是判断是否注册的代码
图②是判断
[Asm] 纯文本查看 复制代码 cmp byte ptr [r13], dil
je 0x7ff65d796f60
2. 这里的 r13 其实大有文章,在右边的FPU窗口,R13上点击右键,跳转到内存区域
给这行下断,就可以得到 R13 在FPU的值
根据上文的cmp,表示这个字节只要是>1 则表示注册成功,
3. 那我们在内存窗口直接改成1试试
红圈的地方改为1
新世界大门打开了,发现不论是标题、还是About窗口,或者是Ctrl+S的弹窗, 都没了未注册,看来这个是关键字段,
为了佐证这个观点,我花费了大量时间去查看它的上下文代码,发现这个是一个类里面的变量,在所有的判断注册的地方都引用
4. 如图,这是About 调用堆栈的第二个代码
图①是调用显示About页面中控件的CALL,
r13 通过 rdx 过来,也就是函数的第二个参数,也就是上图的第④的赋值
下图是第一个调用,也就是About 页面的代码
从 ② 到 ③ 然后到 ④,可以研究出代码是如下结构
[Asm] 纯文本查看 复制代码
rbx = rcx
rbx = [rbx + 0x10]
rdx = rbx
rcx 一般是函数的第一个参数,其实在这里是this的意思,面向对象class中,this一般是函数传递的第一个参数,在上图的注释中也可以看出来。
[C++] 纯文本查看 复制代码
struct RegisterStruct {
bool isRegistered;
}
class main {
public:
byte some[16];
RegisterStruct * registered; //这里也就是 this + 0x10,指向的地址 第一个就是isRegistered
}
既然是一个固定变量,那么说只会随着Sublime主程序销毁才会改变位置。为什么?因为Sublime是采用plugin_command的模式调用所有控件的,这个在跟踪About的时候会发现,即使没看过源代码,也可以猜测出来这些结构。
5. 现在需要的是找个地方将 s13所指向的地址改成1,这样程序就变成了自我注册了
哪里去找呢,必须在启动程序的时候触发的地方,那给标题添加UNREGISTER 的setwindowtitle这段不是正好,
在启动程序时需要设置标题,这里是绝佳的位置,并且我们也研究过那段代码。
我们设置setwindowtext的断点,切换Sublime的Tab,断下之后,找第二个调用堆栈,
这个堆栈是根据配置拼接成为 0xA 0x8 0xC的地方:之前文章说过
未注册 r14b的结果是 0xA 也就是 1010
已注册 r14b的结果是 0x8 也就是 1000
已注册但是过期 r14b是 0xc 也就是 1100
这里没写清楚,上图的是开始拼接unregister字符串的地方,往上面一直翻,可以翻到 mov r14b, r9d
等等,r14b 和 r9d是什么关系?
大家要明白 在call之前的mov都是在给参数赋值,r9d,就是x64位汇编的第4个参数
那么我们就应该找到call本函数的的上一个函数体,给mov r14b, r9d下断,然后等程序断到这里,打开堆栈窗口,第二个就是上一个函数体,
也就是下文要讲解的内容,非常的重要,修改全在这个函数体内。
图①是 堆栈的call
图②是给call赋值参数,也就是r9d 第四个参数
图②可以看到r9d = esi
图①的call的主要功能就是据r9d的bitmask去判断是否拼接UNRESIGTER,自己跟进去看。
那我们要找的就是在这个之前的一段没什么用的代码,替换一段修改r13的内存的代码,慢慢跟,会找到的。
6. 往程序顶部翻,会发现有对esi赋值的地方
图③就是赋值esi的地方
[C++] 纯文本查看 复制代码 //图②
r14d = r8d
r14d |= 4
if([rdx + 1] == true)
{
r14d = r8d //如果注册 设置为是0
}
//图③
esi = r14d;
est |= 0x8;
通过跟踪发现 rdx指向的就是 about页面 r13的地址,也就是是否注册的内存地址,图①箭头地方。
不管rdi+4d8是什么东西,这也是类里面的变量,不用关心,只要最终计算出来的地方是r13就好。
7. 修改上图②是最好的,这里的空间也足够修改了。
将图②的整块区域修改为
先将图2的整块区域全部nop,然后修改成下面的内容
[Asm] 纯文本查看 复制代码 mov byte ptr ds:[rdx], 1 //将rdx的第一个字段修改为 1 也就是 r13 为 1
mov r14d, 0 //设置r14d 为0 表示title不用 UNREGISTER
后面补了5个nop的长度,这段代码就是在 setwindowtext之前,将注册的内存设置为1,这样全局就注册了,第二句是为了title不出现UNREGISTER
并且这个代码在启动的时候就会运行。
程序到此,就实现了自注册,完全破解了。
即使Remove License 也没用,程序还是注册态。
内存补丁(不是文件偏移)
[Asm] 纯文本查看 复制代码 000000000005BFCC:45->C6
000000000005BFCD:8B->02
000000000005BFCE:F0->01
000000000005BFD0:83->BE
000000000005BFD1:CE->00
000000000005BFD2:04->00
000000000005BFD3:38->00
000000000005BFD4:5A->00
000000000005BFD5:01->90
000000000005BFD6:45->90
000000000005BFD7:0F->90
000000000005BFD8:44->90
000000000005BFD9:F0->90
文件修改偏移:
[Asm] 纯文本查看 复制代码
5B3CC: 45->C6
5B3CD: 8B->02
5B3CE: F0->01
5B3D0: 83->BE
5B3D1: CE->00
5B3D2: 04->00
5B3D3: 38->00
5B3D4: 5A->00
5B3D5: 01->90
5B3D6: 45->90
5B3D7: 0F->90
5B3D8: 44->90
5B3D9: F0->90
|