当前位置: 首页 > news >正文

做网站开发 甲方提供资料wordpress 有广告插件下载

做网站开发 甲方提供资料,wordpress 有广告插件下载,长沙网站排名优化,网站见建设更新#xff0c;修改了一下typora的上传脚本#xff0c;把图片全部上传到看雪上了 本文已于2023-08-02首发于个人博客 图片加载不出来#xff0c;放了一个PDF版本在附件里 文中有几张图片是动图#xff0c;如果不会动#xff0c;可以去我的个人博客看 最近破解了一个M…更新修改了一下typora的上传脚本把图片全部上传到看雪上了 本文已于2023-08-02首发于个人博客 图片加载不出来放了一个PDF版本在附件里 文中有几张图片是动图如果不会动可以去我的个人博客看 最近破解了一个MFC程序OriginLab Pro这里记录一下相关过程以及学到的一些东西 软件下载地址下载整个仓库然后和并解压即可 定位激活代码 程序安装完毕之后打开就会弹出激活界面 我们选择使用license进行离线激活 对于这种输入框最后肯定是要使用USER32!GetWindowText*来获取用户输入的在输入框中随便输个字符串然后在windbg中使用bm下个通配符断点 1 2 3 4 5 6 7 0:005 bm user32!getwindowtext*   1: 00007ffba7f06f50 !USER32!GetWindowTextW$filt$0   2: 00007ffba7f06e95 !USER32!GetWindowTextA$filt$0   3: 00007ffba7ed9490 !USER32!GetWindowTextA   4: 00007ffba7eda200 !USER32!GetWindowTextLengthW   5: 00007ffba7edc2f0 !USER32!GetWindowTextW   6: 00007ffba7f59ce0 !USER32!GetWindowTextLengthA 之后点击OK 实际测试发现在我们点击OK之前这些断点就会被反复触发这样会干扰我们找到真正的license处理逻辑因此我们需要改进一下先在COMCTL32!Button_WndProc0x7fb下断点这个断点只有在点击按钮的时候才会被触发然后点击OK该断点触发之后再下上面的通配符断点即可定位到真正的license处理逻辑 我们使用IDA来看一下调用栈中编号为02的位置首先这个代码位于C:\Program Files\OriginLab\Origin2023b\ou.dll 计算出偏移量 1 2 3 4 5 6 7 8 9 10 11 12 0:000 lm m *ou* Browse full module list start             end                 module name 0000000010000000 000000001046d000   Resource   (deferred)             00007ffb53b40000 00007ffb54452000   SogouPy    (deferred)             00007ffb54460000 00007ffb546a3000   sogoutsf   (deferred)             00007ffb54d90000 00007ffb54de1000   OUIM       (deferred)             00007ffb76fb0000 00007ffb76feb000   OCcontour   (deferred)             00007ffb79400000 00007ffb794a4000   Outl       (deferred)             00007ffb794b0000 00007ffb79be7000   ou         (export symbols)       C:\Program Files\OriginLab\Origin2023b\ou.dll 0:000 ? ou!COUxlView::xlWorksheetToNativeOrigin0x23489-00007ffb794b0000 Evaluate expression: 1271337  0000000000136629 根据该偏移量在IDA中跳转到对应的位置 1 2 3 4 .text:000000018013661C                 lea     rdx, [rsp38harg_18] .text:0000000180136621                 mov     rcx, rbx .text:0000000180136624                 call    ?GetWindowTextWCWndQEBAXAEAV?$CStringT_WV?$StrTraitMFC_DLL_WV?$ChTraitsCRT_WATLATLZ ; CWnd::GetWindowTextW(ATL::CStringTwchar_t,StrTraitMFC_DLLwchar_t,ATL::ChTraitsCRTwchar_t ) .text:0000000180136629                 lea     rcx, [rsp38harg_18] 根据我们的经验一眼就能看出rdx是传出参数也就是说[rsp38harg_18]会保存我们输入的license 分析汇编代码 把函数sub_180136600整体给看了一下并没有找到激活相关的代码那我们就接着看调用栈中编号03的代码也就是函数sub_180134090 ou!sub_180134090 该函数中的关键代码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 .text:00000001801340AA                 lea     rcx, [rsp28harg_8] .text:00000001801340AF                 call    cs:??0CStringUTF8QEAAXZ ; CStringUTF8::CStringUTF8(void) .text:00000001801340B5                 nop .text:00000001801340B6                 lea     rdx, [rdi490h] .text:00000001801340BD                 lea     r8, [rsp28harg_8] .text:00000001801340C2                 mov     rcx, rdi .text:00000001801340C5                 call    sub_180136600 .text:00000001801340CA                 mov     rcx, [rsp28harg_8] .text:00000001801340CF                 call    sub_18012EF30 .text:00000001801340D4                 mov     ebx, eax .text:00000001801340D6                 lea     rcx, [rsp28harg_0] .text:00000001801340DB                 call    cs:??0CStringUTF8QEAAXZ ; CStringUTF8::CStringUTF8(void) .text:00000001801340E1                 nop .text:00000001801340E2                 mov     r9d, ebx .text:00000001801340E5                 lea     r8, aBc04       ; BC04: .text:00000001801340EC                 lea     rdx, aSD_2      ; %s%d .text:00000001801340F3                 lea     rcx, [rsp28harg_0] .text:00000001801340F8                 call    cs:?FormatCStringUTF8QEAAXPEBDZZ ; CStringUTF8::Format(char const *,...) .text:00000001801340FE                 mov     r8d, 1 .text:0000000180134104                 mov     rdx, [rsp28harg_0] .text:0000000180134109                 lea     ecx, [r814h] .text:000000018013410D                 call    LABUTIL_diagnostics .text:0000000180134112                 nop .text:0000000180134113                 lea     rcx, [rsp28harg_0] .text:0000000180134118                 call    cs:__imp_??1CStringUTF8QEAAXZ ; CStringUTF8::~CStringUTF8(void) .text:000000018013411E                 mov     eax, cs:dword_1803D4898 .text:0000000180134124                 test    ebx, ebx .text:0000000180134126                 cmovnz  eax, ebx .text:0000000180134129                 mov     cs:dword_1803D4898, eax .text:000000018013412F                 lea     rcx, [rsp28harg_8] .text:0000000180134134                 call    cs:__imp_??1CStringUTF8QEAAXZ ; CStringUTF8::~CStringUTF8(void) 我们在ou1340C5下断点观察函数sub_180136600调用完成后第二个参数和第三个参数的情况 很明显第3个参数rsp28harg_8是传出参数调用完成后会保存我们的license字符串 继续观察这段代码我们可以发现license text作为第1个参数传给了函数sub_18012EF30返回值放到ebx中并最终作为函数CStringUTF8::Format的第4个参数然后这个函数就结束了 那现在我们就进入函数sub_18012EF30中一探究竟 ou!sub_18012EF30 首先我们通过windbg的调试可以确定下面这个函数的两次调用分别返回了字符串REGID和FSN 后面函数sub_180136A90也被调用了两次我们先看第一次调用的参数传入情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 0:000 dc poi(rcx) 0000015feea4c9e8  73696874 20736920 6563696c 2065736e  this is license 0000015feea4c9f8  74786574 72003300 6e696769 5c62614c  text.3.riginLab\ 0000015feea4ca08  6563694c 0065736e 00756a70 00adf00d  License.pju..... 0000015feea4ca18  eea4cb58 0000015f 0000002f baadf00d  X..._.../....... 0000015feea4ca28  65780035 646f4d64 6e496c65 2e626968  5.xedModelInhib. 0000015feea4ca38  00666466 61745320 64656b63 73694820  fdf. Stacked His 0000015feea4ca48  72676f00 6f2e6d61 00756a70 baadf00d  .ogram.opju..... 0000015feea4ca58  eea4ca18 0000015f 0000002f baadf00d  ...._.../....... 0:000 dc poi(rdx) 0000015ffa7c2a08  49474552 20730044 6563696c 0065736e  REGID.s license. 0000015ffa7c2a18  fa7c2978 0000015f 0000000f baadf00d  x)|._........... 0000015ffa7c2a28  003d4c43 33323632 62302e00 005c6100  CL.2623..0b.a\. 0000015ffa7c2a38  fa7c2a18 0000015f 0000000f baadf00d  .*|._........... 0000015ffa7c2a48  72747845 76650061 6c2e6c61 00006369  Extra.eval.lic.. 0000015ffa7c2a58  00000001 00000001 0000000f baadf00d  ................ 0000015ffa7c2a68  44500003 2e324345 00464446 baadf00d  ..PDEC2.FDF..... 0000015ffa7c2a78  00000001 00000002 0000000f baadf00d  ................ 0:000 dc poi(r8) 00007ffb8a77f050  00000000 00000000 00000000 00000000  ................ 00007ffb8a77f060  8a77a8f8 00007ffb 00000020 00000fff  ..w..... ....... 00007ffb8a77f070  00015262 00000000 fd2fff10 0000015f  bR......../._... 00007ffb8a77f080  fa7c3e78 0000015f 8a7721b0 00007ffb  x|._....!w..... 00007ffb8a77f090  8a7721c0 00007ffb ffffffff ffffffff  .!w............. 00007ffb8a77f0a0  ffffffff 00000000 00000000 00000000  ................ 00007ffb8a77f0b0  00000000 00000000 020007d0 00000000  ................ 00007ffb8a77f0c0  8a77a8f8 00007ffb 00000040 00000fff  ..w............ 0:000 r r9 r9000000000000000b 1p我们输入的license text2pREGID3p传出参数4p硬编码的值0xB ou!sub_180136A90 现在我们进入函数sub_180136A90这个函数中调用的都是CString类的一些函数因此很容易理清逻辑这个函数会对我们的输入的license字符串作如下处理 license text转为大写获取REGID在license text中的index如果index为-1license text中不存在REGID或者0REGID位于license text的开头则返回1同时传出参数为空否则从license text的indexlen(REGID)1的位置开始截取长度为0xB的字符串填充到传出参数另外第一个参数也就是我们输入的license text也发生了变化index及之后的字符都被丢弃了 然后再次调用 可以看到该函数第二次调用的返回值会直接影响到最终的返回值0x191及401也就是license text验证失败的错误代码 很显然我们不希望最后返回401因此我们要控制al不为0那我们就可以构造出如下的license text来控制al为1 1 0FSN0123456789abcdefghijkREGIDABCDEFGHIJKLMNOPQRSTUVWXYZ 然后函数sub_180136A90两次调用的传出参数将会分别作为函数okuCountTotalSeries的参数被调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 0:000 dc rcx 0000015ffa7c2a28  45444342 49484746 004c4b4a 005c6174  BCDEFGHIJKL.ta\. 0000015ffa7c2a38  fa7c2958 0000015f 0000000f baadf00d  X)|._........... 0000015ffa7c2a48  003d4c43 33323632 62302e00 005c6100  CL.2623..0b.a\. 0000015ffa7c2a58  00000001 00000001 0000000f baadf00d  ................ 0000015ffa7c2a68  44500003 2e324345 00464446 baadf00d  ..PDEC2.FDF..... 0000015ffa7c2a78  00000001 00000002 0000000f baadf00d  ................ 0000015ffa7c2a88  44004303 2e334345 00464446 baadf00d  .C.DEC3.FDF..... 0000015ffa7c2a98  00000001 00000001 0000000f baadf00d  ................ 0:000 dc rdx 0000015feea4c868  34333231 38373635 63626139 67666564  123456789abcdefg 0000015feea4c878  69006968 62614c6e 6369005c 65736e65  hi.inLab\.icense 0000015feea4c888  51000000 55545352 59585756 0000005a  ...QRSTUVWXYZ... 0000015feea4c898  eea4cb98 0000015f 0000002f baadf00d  ...._.../....... 0000015feea4c8a8  4e534630 33323130 37363534 62613938  0FSN0123456789ab 0000015feea4c8b8  66656463 6a696867 6369006b 65736e65  cdefghijk.icense 0000015feea4c8c8  65630000 0065736e 36323532 00003332  ..cense.252623.. 0000015feea4c8d8  00000001 00000013 0000002f baadf00d  ......../....... ok!okuCountTotalSeries 该函数位于C:\Program Files\OriginLab\Origin2023b\ok.dll 从上图中可以看出我们需要控制函数okuCountTotalSeries的返回值不为0 那么我们就需要控制该函数内部的这两个分支不能跳到loc_180E0C1D7 ok!sub_180E0A430 该函数代码不多逻辑也是相当的简单 就是把我们传给函数okuCountTotalSeries的第2个参数也就是字符串 1 2 123456789abcdefghi 012345678901234567 的0xB处开始拷贝出来就是cdefghi返回值就是atol函数的返回值很显然当前的注册码是没有办法转换成long的因此我们需要把cdefghi改成1234567 现在我们的注册码就变成了 1 0FSN0123456789ab1234567jkREGIDABCDEFGHIJKLMNOPQRSTUVWXYZ ok!sub_180DF8F70 这个函数的内容有一点长其传入的参数如下 1 2 3 4 5 6 7 8 9 10 11 12 13 0:000 dc rcx 0000015ffa7c3e88  45444342 49484746 004c4b4a 00006369  BCDEFGHIJKL.ic.. 0000015ffa7c3e98  00000001 00000001 0000000f baadf00d  ................ 0000015ffa7c3ea8  6d650030 005c7365 00332e32 00007300  0.emes\.2.3..s.. 0000015ffa7c3eb8  00000001 00000009 0000000f baadf00d  ................ 0000015ffa7c3ec8  57746547 6449646e 746e0078 006c6f72  GetWndIdx.ntrol. 0000015ffa7c3ed8  00000001 0000000f 0000000f baadf00d  ................ 0000015ffa7c3ee8  4e746547 65657254 6e616843 00736567  GetNTreeChanges. 0000015ffa7c3ef8  00000001 0000000d 0000000f baadf00d  ................ 0:000 r rdx rdx0000000000000000 0:000 r r8 r80000000000000000 我不想进去看了直接看一下返回值返回值是一个整型数然后和函数sub_180E0A430的返回值进行了比较如果两者不相等最终就会返回0 那么很简单我们只需要控制sub_180E0A430的返回值和该函数的返回值一样即可当前函数的返回值是0x42dded即4382189再次更新我们的注册码 1 0FSN0123456789ab4382189jkREGIDABCDEFGHIJKLMNOPQRSTUVWXYZ 好了现在我们重新回到ou.dll的函数sub_18012EF30 ou!loc_18012EFDC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mov     dl, 22h ;  lea     rcx, [rbparg_10] call    cs:?ReverseFindCStringUTF8QEBAHDZ ; CStringUTF8::ReverseFind(char) lea     r8d, [rax1] lea     rdx, [rbpvar_18] lea     rcx, [rbparg_10] call    cs:?LeftCStringUTF8QEBA?AV1HZ ; CStringUTF8::Left(int) nop mov     rax, [rbpvar_20] mov     [rsp50hvar_30], rax mov     r9, [rbparg_18] xor     r8d, r8d lea     rdx, [rbparg_8] lea     rcx, [rbpvar_18] call    sub_1801308E0 mov     ecx, 191h test    eax, eax cmovz   edi, ecx lea     rcx, [rbpvar_18] call    cs:__imp_??1CStringUTF8QEAAXZ ; CStringUTF8::~CStringUTF8(void) jmp     short loc_18012F033 上面汇编代码中的[rbparg_10]就是函数sub_180136A90的第1个参数我们前面已经知道了该函数会改变自己第一个参数的内容就是会把REGID和FSN及后面的字符都丢掉那么到这里[rbparg_10]的值就是 1 0 这段代码做的事就是在[rbparg_10]找到最后一次出现的位置然后丢弃该位置之后的字符 最后调用函数sub_1801308E0 ou!sub_1801308E0 我们先看一下参数传入情况 1p前面使用截取出来的字符串2p传出参数3p04p123456789ab43821895pBCDEFGHIJKL 该函数会检查第一个参数是否是空字符串因为我们没有所以第一道检查就挂了 另外就是该函数的返回值也需要进行控制根据loc_18012EFDC中的内容 1 2 3 mov     ecx, 191h test    eax, eax cmovz   edi, ecx 只有eax不为0edi才不会变成0x191 因此我们需要经过该函数的重重检查到达loc_180130A1F 前面的检查都由CString类的函数完成分析起来很简单这里不再赘述最终形成的注册码为 1 INCREMENTFEATUREorglabSIGN123456789FSN09876543278L5824771TUVWXYZREGIDFSNABCDEFGHIJKLMNOPQRSTUVWXYZ 但是输入该注册码之后并没有提示我们注册成功虽然没有401报错了但是我们的软件仍未被激活 仔细审查函数sub_1801308E0的代码可以在函数尾部发现有一个叫做COKAccess::GetTempViewportLimits的函数被调用其第1个参数为 1 INCREMENTFEATUREorglabSIGN123456789 进入该函数一路跟到了ok.dll的sub_18012DDA0 ok!sub_18012DDA0 在该函数下断点我们可以观察到注册码中的下面三部分被存储到了内存的特定位置中 1 2 3 INCREMENTFEATUREorglabSIGN123456789 9876543278L5824771 SNABCDEFGHI 我们记录下这三个字符串存储的内存地址然后下内存读的条件断点 通过内存访问断点定位检测代码 我直接在这三个内存地址上下内存读断点 1 2 3 ba r1 00000218db5dab88 ba r1 00000218db5dac08 ba r1 00000218dc168aa8 最后在第二个断点被触发时得到如下调用栈 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Breakpoint 1 hit ok!OSetNumericSettings::operator0x403b: 00007ffc178eec1b 0f95c0          setne   al 0:000 k  # Child-SP          RetAddr               Call Site 00 000000adbfdff558 00007ffc178ec37b     ok!OSetNumericSettings::operator0x403b 01 000000adbfdff560 00007ffc17f4eae3     ok!OSetNumericSettings::operator0x179b 02 000000adbfdff5a0 00007ffc17f54649     ok!okfxDoNewLegendEntries0x21b3 03 000000adbfdff5e0 00007ffc17f54f6d     ok!GetObjectPlotCategory::ObjectSeriesSetType0x1229 04 000000adbfdff630 00007ffc17f50673     ok!GetObjectPlotCategory::ObjectSeriesSetType0x1b4d 05 000000adbfdffcb0 00007ffc17f535c1     ok!GetObjectPlotCategory::DataSeriesGetProcessedData0xe93 06 000000adbfdffce0 00007ffc17955ded     ok!GetObjectPlotCategory::ObjectSeriesSetType0x1a1 07 000000adbfdffd30 00007ffc1a962731     ok!COKAccess::OkOnItemReDraw0x10d 08 000000adbfdffdb0 00007ffc33c70a7c     ou!COriginApp::OnIdle0xd1 09 000000adbfdffe00 00007ffc33ca3c20     mfc140u!CWinThread::Run0x5c [D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\thrdcore.cpp  621] 0a 000000adbfdffe40 00007ff6625ea44e     mfc140u!AfxWinMain0xc0 [D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\winmain.cpp  61] 0b 000000adbfdffe80 00007ffc651a7614     Origin640xa44e 0c 000000adbfdffec0 00007ffc654a26b1     KERNEL32!BaseThreadInitThunk0x14 0d 000000adbfdffef0 0000000000000000     ntdll!RtlUserThreadStart0x21 稍加整理即可得到函数的调用顺序我们只取出调用栈中的前几个即可整理出来如下的调用栈 1 2 3 4 5 6 7 sub_180793590     - sub_180790520   调用点0x18079066E         - sub_180794B10             - sub_180794600                 - sub_18078EAC0                     - sub_18012C360                         - sub_18012EC10 这里面的函数代码一个比一个长简单放一个拓扑图感受一下 所以这些函数我都是大致浏览了一下其中函数sub_180790520吸引到了我的注意 在下面这个地方0x18079066E函数调用了sub_180794B10而这个函数的返回值决定了分支的走向 继续往下浏览我发现在右边的分支最终会调用函数COKAccess::UpdateMainWinTitle这个看起来很不错因为如果是激活失败的话也没必要更新主窗口的标题可以看到我当前的测试软件的窗口标题中有一个Expired同时左边的分支并没有什么有趣的东西因此我们尝试把函数sub_180794B10的返回值强制修改为1 patch程序 这里之所以选择修改返回值而不是分析函数sub_180794B10的代码是因为这个函数实在是太复杂了不如赌一把直接修改返回值 看一下缩略图就知道这个函数有多复杂了比我上面贴的那个还复杂 想要把这个函数分析明白需要很多时间所以我选择直接patch 我们最终会从左边那个分支返回所以我们需要把mov eax, ebx修改掉保证最后的返回值非0 这个指令对应的机器码如下 1 2 3 0:001 u ok7954CB ok!GetObjectPlotCategory::ObjectSeriesSetType0x20ab: 00007ffc17f554cb 8bc3            mov     eax,ebx 只占用2个字节因此我们需要搞一个只占用2字节而且还能保证eax非0的指令 如上图所示mov al, 1就正好符合我们的需求我们只需要使用管理员权限打开IDA将ok.dll的0x1807954CB修改为b001即可 使用API HOOK技术定位消息发送代码 我当时以为这把肯定能搞定了结果输入注册码之后弹出了如下消息框真的是太难了 现在我要找一下这个窗是怎么弹出来的在user32!messageboxw下断点看一下调用栈 1 2 3 4 5 6 7 Breakpoint 0 hit USER32!MessageBoxW: 00007ffc64609750 4883ec38        sub     rsp,38h 0:000 k  # Child-SP          RetAddr               Call Site 00 00000046963fe638 00007ffc1a939814     USER32!MessageBoxW 01 00000046963fe640 00007ffc33c8782e     ou!CMainFrame::WindowProc0x704 这个消息框是在CMainFrame::WindowProc函数的0x18003980F位置被调用的 这个函数看名字再加上IDA分析出来的参数情况基本上能猜出来是通过消息触发的后两个参数应该就是lParam和wParam和SendMessage的参数对应 我们可以使用IDA的分支图追溯一下函数MessageBoxW的第2和第3个参数就是消息框的标题和内容是哪里来的 最终可以定位到这两个参数是在0x18003940F 和0x180039422被初始化的从这个地方的函数名称和参数传入情况就能看出来第一个参数是传出参数将会保存一个字符串并且这个函数两次调用其第2个参数分别是CMainFrame::WindowProc的第4和第3个参数 因此我们可以下下面这样的断点来观察该函数调用前后的参数情况 1 2 3 ba e1 ou3940F r rdx;g ba e1 ou39422 dc poi(rsp48);r rdx;g ba e1 ou39428 dc poi(rsp40);g 得到如下结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 rdx0000000000003f0e 000001d9d2b91dc8  00740041 00650074 0074006e 006f0069  A.t.t.e.n.t.i.o. 000001d9d2b91dd8  0021006e abab0000 abababab abababab  n.!............. 000001d9d2b91de8  abababab feeeabab 00000000 00000000  ................ 000001d9d2b91df8  00000000 00000000 feeefeee feeefeee  ................ 000001d9d2b91e08  bd768892 00fbed99 d2a8e380 000001d9  ..v............. 000001d9d2b91e18  c305e490 000001d9 feeefeee feeefeee  ................ 000001d9d2b91e28  feeefeee feeefeee feeefeee feeefeee  ................ 000001d9d2b91e38  feeefeee feeefeee feeefeee feeefeee  ................ rdx0000000000003fb6 000001d9d2a8e398  006f0059 00720075 00460020 0045004c  Y.o.u.r. .F.L.E. 000001d9d2a8e3a8  006c0058 0020006d 0069006c 00650063  X.l.m. .l.i.c.e. 000001d9d2a8e3b8  0073006e 00200065 00690066 0065006c  n.s.e. .f.i.l.e. 000001d9d2a8e3c8  00690020 00200073 006e0069 00610076   .i.s. .i.n.v.a. 000001d9d2a8e3d8  0069006c 002e0064 abab0000 abababab  l.i.d........... 000001d9d2a8e3e8  abababab abababab feeeabab feeefeee  ................ 000001d9d2a8e3f8  feeefeee feeefeee 00000000 00000000  ................ 000001d9d2a8e408  00000000 00000000 feeefeee feeefeee  ................ 可以看到两次调用的第2个参数分别为0x3f0e和0x3fb6我们选择0x3fb6作为过滤条件因为标题区分度不够高可能别的窗口也会使用同样的标题而内容重复的概率不高那么我们就可以HOOK住消息发送函数检测传进来的wParam是否为0x3fb6消息发送函数我知道的一共有两个一个是SendMessage另一个是PostMessage我当时先HOOK的SendMessageW但是并没有拦截到wParam值为0x3fb6的调用后面我又HOOK了PostMessageW成功拦截下面我记录一下我HOOK这两个API的过程 api hook的技术细节 我在网上搜了搜给出的方案是把原始函数的前面几个字节替换成跳转到我们的hook函数的指令然后在hook函数中对参数进行过滤之后恢复原始函数的前面几个字节再去调用原始函数并返回 但是这个并不满足我的需求由于在hook函数内修复了原始函数所以他只能hook一次 我后来想的办法是在hook函数内修复原始函数调用原始函数后保存返回值然后再修改原始函数的前几个字节重新hook住这个函数再返回前面保存的返回值但是这样在多线程中会出现问题最后在汪哥的提醒下找到了下面的hook方式 最终导致的结果就是当PostMessageW被调用的时候指令的走向就变成了下面这样 原理已经清楚代码就很容易写了如下图所示我们顺利定位到了发送该消息的调用栈 这条消息实际上是由sub_180793590发送的调用位置在0x180793625 而这个函数又是在OkOnItemReDraw的0x180195DE8 位置调用的观察该函数的分支走向并结合里面调用的各个函数名分析即可定位到关键判断语句的位置0x180195D3E 1 2 test    eax, eax jnz     loc_18019624F 故技重施把jnz修改为jz即可前者的机器码为0F 85后者的机器码为0F 84修改之后重新打开OriginPro没有任何弹窗也不会出现过一段时间就自动退出的情况虽然查看注册信息仍然是未激活状态但是已经不影响正常使用了 OK这次的破解就到这儿吧不足之处还望各位师傅指点 本篇文章中用到的工具以及patch之后的DLL都打包放到这里了
http://www.zqtcl.cn/news/886407/

相关文章:

  • 自适应科技公司网站模板做网站的公司深
  • 网站怎么吸引流量用淘宝做公司网站
  • asp做的网站后台怎么进去老河口城乡建设局网站
  • 中铁建设集团有限公司官方网站wordpress质感
  • 那个网站点击率高pc网站自动生成app
  • 东莞营销型网站建站淘金企业网站建设
  • 怎么用模板做网站手机python编程软件
  • 做视频网站都需要什么软件下载广东网站建设哪家专业
  • 开淘宝的店铺网站怎么做网页设计需要学什么书
  • 如何做收费网站微信小程序开发教程详解
  • 软件下载网站如何履行安全管理义务网站合同书
  • 普宁17网站一起做淘宝网站建设 丽水
  • 网站注册需要多少钱wordpress缓存失败
  • 西安h5响应式网站施工企业安全生产管理规范最新版
  • 电商平台网站建设如何安装网站模版
  • wordpress攻击跳转seo营销软件
  • 广东中山市做网站python做的网站如何部署
  • VPS做镜像网站wordpress 安装七牛
  • 雄安做网站优化的公司小程序开发公司哪里强
  • 做的网站没有注册国家建设部网站倪虹
  • 中英文网站怎么实现做网站有名的公司
  • 先网站开发后软件开发显示网站运行时间代码
  • 品牌网站制作流程图百度网页版入口页
  • 哪些人需要做网站网站开发工程师 招聘
  • 东莞网站建设多长时间如何将网址提交到一些权重比较高的网站
  • 阳江网站seo公司wordpress建站博客
  • 我想做京东网站淘宝怎么做的wordpress淘宝联盟转链
  • 虚拟钱包对接网站开发视频教程营销型网站建设要懂代码吗
  • 莱州教育网站一站式网站搭建
  • 开发网站开票名称是什么捕鱼游戏网站开发商