zoukankan      html  css  js  c++  java
  • [反汇编练习] 160个CrackMe之007

    [反汇编练习] 160个CrackMe之007.

    本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注册机的东西。

    其中,文章中按照如下逻辑编排(解决如下问题):

    1、使用什么环境和工具

    2、程序分析

    3、思路分析和破解流程

    4、注册机的探索

    ----------------------------------

    提醒各位看客: 如果文章中的逻辑看不明白,那你一定是没有亲手操刀!OD中的跳转提示很强大,只要你跟踪了,不用怎么看代码就理解了!

    ----------------------------------

    1、工具和环境:

    WinXP SP3 + 52Pojie六周年纪念版OD + PEID + 汇编金手指。

    160个CrackMe的打包文件。

    下载地址: http://pan.baidu.com/s/1xUWOY  密码: jbnq

    注:

    1、Win7系统对于模块和程序开启了随机初始地址的功能,会给分析带来很大的负担,所以不建议使用Win7进行分析。

    2、以上工具都是在52PoJie论坛下的原版程序,NOD32不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。

    wps_clip_image-142827

    2、程序分析:

    想要破解一个程序,必须先了解这个程序。所以,在破解过程中,对最初程序的分析很重要,他可以帮助我们理解作者的目的和意图,特别是对于注册码的处理细节,从而方便我们反向跟踪和推导。

    和上一节一样,打开CHM,选择第7个aLoNg3x.2,保存下来。运行程序,程序界面如下:

    image

    使用PEID查一下,Delphi 4.0 - 5.0。点一下About-Help,看完之后和上一个要求一样。不用想了,直接上IDR分析。

    3、思路分析和破解流程

    IDR打开后如图:

    3

    我们先看一下窗口信息(F5):

    1

    我们发现,除了第一个register按钮之后,还有一个again按钮。看来这个程序意思很明确点击完Reg之后还需要通过again按钮的验证。我们在树列表中查看下按钮对应事件的关系。

    首先,分析Register的事件:

    双击IDR最下面的列表中的RegisterClick.event,右上角会显示对应的反汇编。

    根据上一个程序的经验,大概地分析一下:

    Delphi字符串函数反汇编参考:http://www.cnblogs.com/bbdxf/p/3787684.html

     _CrackMe200::TPrincipale.RegisterzClick
     00442F28    push       ebp
     00442F29    mov        ebp,esp
     00442F2B    add        esp,0FFFFFFF8
     00442F2E    push       ebx
     00442F2F    push       esi
     00442F30    xor        ecx,ecx
     00442F32    mov        dword ptr [ebp-8],ecx
     00442F35    mov        ebx,eax
     00442F37    xor        eax,eax
     00442F39    push       ebp
     00442F3A    push       443022
     00442F3F    push       dword ptr fs:[eax]
     00442F42    mov        dword ptr fs:[eax],esp
     00442F45    lea        edx,[ebp-8]
     00442F48    mov        eax,dword ptr [ebx+2DC]; TPrincipale.Codice:TEdit
     00442F4E    call       TControl.GetText
     00442F53    mov        eax,dword ptr [ebp-8]
     00442F56    lea        edx,[ebp-4]
     00442F59    call       @ValLong
     00442F5E    mov        esi,eax
     00442F60    cmp        dword ptr [ebp-4],0
    >00442F64    je         00442F9D
     00442F66    mov        eax,443038; 'You MUST insert a valid Long Integer Value in the Code Editor... Thank you :)'
     00442F6B    call       ShowMessage
     00442F70    lea        edx,[ebp-8]
     00442F73    mov        eax,dword ptr [ebx+2DC]; TPrincipale.Codice:TEdit
     00442F79    call       TControl.GetText
     00442F7E    mov        eax,dword ptr [ebp-8]
     00442F81    call       00442A8C
     00442F86    mov        [00445830],eax; gvar_00445830
     00442F8B    mov        edx,443090; '0'
     00442F90    mov        eax,dword ptr [ebx+2DC]; TPrincipale.Codice:TEdit
     00442F96    call       TControl.SetText
    >00442F9B    jmp        0044300C
     00442F9D    test       esi,esi
    >00442F9F    jle        00442FFB
     00442FA1    lea        edx,[ebp-8]
     00442FA4    mov        eax,dword ptr [ebx+2D8]; TPrincipale.Nome:TEdit
     00442FAA    call       TControl.GetText
     00442FAF    mov        ecx,dword ptr [ebp-8]
     00442FB2    mov        edx,esi
     00442FB4    mov        eax,[00445830]; 0x0 gvar_00445830
     00442FB9    call       004429A8	; // 关键CALL
     00442FBE    test       al,al
    >00442FC0    je         00442FF2	; // 关键跳转
     00442FC2    xor        edx,edx		;// 将注册按钮隐藏,然后显示出来那个again按钮
     00442FC4    mov        eax,dword ptr [ebx+2CC]; TPrincipale.Registerz:TButton
     00442FCA    call       TControl.SetVisible
     00442FCF    mov        dl,1
     00442FD1    mov        eax,dword ptr [ebx+2E8]; TPrincipale.Again:TButton
     00442FD7    call       TControl.SetVisible
     00442FDC    xor        edx,edx
     00442FDE    mov        eax,dword ptr [ebx+2D8]; TPrincipale.Nome:TEdit
     00442FE4    mov        ecx,dword ptr [eax]
     00442FE6    call       dword ptr [ecx+60]; TControl.SetEnabled
     00442FE9    xor        eax,eax
     00442FEB    mov        [00445830],eax; gvar_00445830
    >00442FF0    jmp        0044300C
     00442FF2    xor        eax,eax
     00442FF4    mov        [00445830],eax; gvar_00445830
    >00442FF9    jmp        0044300C
     00442FFB    mov        eax,44309C; 'Please... The Code Must be > 0'
     00443000    call       ShowMessage
     00443005    xor        eax,eax
     00443007    mov        [00445830],eax; gvar_00445830
     0044300C    xor        eax,eax
     0044300E    pop        edx
     0044300F    pop        ecx
     00443010    pop        ecx
     00443011    mov        dword ptr fs:[eax],edx
     00443014    push       443029
     00443019    lea        eax,[ebp-8]
     0044301C    call       @LStrClr
     00443021    ret
    <00443022    jmp        @HandleFinally
    <00443027    jmp        00443019
     00443029    pop        esi
     0044302A    pop        ebx
     0044302B    pop        ecx
     0044302C    pop        ecx
     0044302D    pop        ebp
     0044302E    ret

    根据函数的名称,我们很容易分析出了关键Call 004429A8, 在CALL下面的JE就是爆破的关键跳转。

    将exe程序拖到OD中打开,根据IDR中的地址,转到(Ctrl+G)开头地址:00442F28。在程序中输入伪码,参照IDR中的汇编,修改关键的跳转JE 00442FF2,选中JE->右键->Binary->Fill with NOPs。在程序中随意输入,点击Register按钮,发现注册按钮不见了,again按钮出来了。

    我们继续在IDR中找到againClick.event,双击进去,继续分析一下:

     _CrackMe200::TPrincipale.AgainClick
     004430BC    push       ebp
     004430BD    mov        ebp,esp
     004430BF    push       0
     004430C1    push       0
     004430C3    push       0
     004430C5    push       ebx
     004430C6    push       esi
     004430C7    mov        ebx,eax
     004430C9    xor        eax,eax
     004430CB    push       ebp
     004430CC    push       44322D
     004430D1    push       dword ptr fs:[eax]
     004430D4    mov        dword ptr fs:[eax],esp
     004430D7    lea        edx,[ebp-0C]
     004430DA    mov        eax,dword ptr [ebx+2DC]; TPrincipale.Codice:TEdit
     004430E0    call       TControl.GetText
     004430E5    mov        eax,dword ptr [ebp-0C]
     004430E8    lea        edx,[ebp-4]
     004430EB    call       @ValLong
     004430F0    mov        esi,eax
     004430F2    cmp        dword ptr [ebp-4],0
    >004430F6    je         00443132
     004430F8    mov        eax,443244; 'You MUST insert a valid Long Integer Value in the Code Editor... Thank you :)'
     004430FD    call       ShowMessage
     00443102    lea        edx,[ebp-0C]
     00443105    mov        eax,dword ptr [ebx+2DC]; TPrincipale.Codice:TEdit
     0044310B    call       TControl.GetText
     00443110    mov        eax,dword ptr [ebp-0C]
     00443113    call       00442A8C
     00443118    mov        [00445830],eax; gvar_00445830
     0044311D    mov        edx,44329C; '0'
     00443122    mov        eax,dword ptr [ebx+2DC]; TPrincipale.Codice:TEdit
     00443128    call       TControl.SetText
    >0044312D    jmp        0044320F
     00443132    test       esi,esi
    >00443134    jle        004431FE
     0044313A    lea        edx,[ebp-0C]
     0044313D    mov        eax,dword ptr [ebx+2D8]; TPrincipale.Nome:TEdit
     00443143    call       TControl.GetText
     00443148    mov        ecx,dword ptr [ebp-0C]
     0044314B    mov        edx,esi
     0044314D    mov        eax,[00445830]; 0x0 gvar_00445830
     00443152    call       004429A8
     00443157    test       al,al
    >00443159    je         004431CE
     0044315B    xor        edx,edx
     0044315D    mov        eax,dword ptr [ebx+2E8]; TPrincipale.Again:TButton
     00443163    call       TControl.SetVisible
     00443168    lea        edx,[ebp-8]
     0044316B    mov        eax,[0044582C]; 0x0 gvar_0044582C:TPrincipale
     00443170    call       TControl.GetText
     00443175    lea        eax,[ebp-8]
     00443178    call       UniqueString
     0044317D    mov        byte ptr [eax+5],65
     00443181    lea        eax,[ebp-8]
     00443184    call       UniqueString
     00443189    mov        byte ptr [eax+6],64
     0044318D    lea        eax,[ebp-8]
     00443190    mov        ecx,13
     00443195    mov        edx,0C
     0044319A    call       @LStrDelete
     0044319F    lea        edx,[ebp-0C]
     004431A2    mov        eax,dword ptr [ebx+2D8]; TPrincipale.Nome:TEdit
     004431A8    call       TControl.GetText
     004431AD    mov        edx,dword ptr [ebp-0C]
     004431B0    lea        eax,[ebp-8]
     004431B3    call       @LStrCat
     004431B8    mov        edx,dword ptr [ebp-8]
     004431BB    mov        eax,[0044582C]; 0x0 gvar_0044582C:TPrincipale
     004431C0    call       TControl.SetText
     004431C5    xor        eax,eax
     004431C7    mov        [00445830],eax; gvar_00445830
    >004431CC    jmp        0044320F
     004431CE    xor        eax,eax
     004431D0    mov        [00445830],eax; gvar_00445830
     004431D5    xor        edx,edx
     004431D7    mov        eax,dword ptr [ebx+2E8]; TPrincipale.Again:TButton
     004431DD    call       TControl.SetVisible
     004431E2    mov        dl,1
     004431E4    mov        eax,dword ptr [ebx+2CC]; TPrincipale.Registerz:TButton
     004431EA    call       TControl.SetVisible
     004431EF    mov        dl,1
     004431F1    mov        eax,dword ptr [ebx+2D8]; TPrincipale.Nome:TEdit
     004431F7    mov        ecx,dword ptr [eax]
     004431F9    call       dword ptr [ecx+60]; TControl.SetEnabled
    >004431FC    jmp        0044320F
     004431FE    mov        eax,4432A8; 'Please... The Code Must be > 0'
     00443203    call       ShowMessage
     00443208    xor        eax,eax
     0044320A    mov        [00445830],eax; gvar_00445830
     0044320F    xor        eax,eax
     00443211    pop        edx
     00443212    pop        ecx
     00443213    pop        ecx
     00443214    mov        dword ptr fs:[eax],edx
     00443217    push       443234
     0044321C    lea        eax,[ebp-0C]
     0044321F    call       @LStrClr
     00443224    lea        eax,[ebp-8]
     00443227    call       @LStrClr
     0044322C    ret
    <0044322D    jmp        @HandleFinally
    <00443232    jmp        0044321C
     00443234    pop        esi
     00443235    pop        ebx
     00443236    mov        esp,ebp
     00443238    pop        ebp
     00443239    ret

    大概地一看,是不是发现他们的逻辑基本和Register的差不多?关键Call也一样。没关系,我们继续在JE 004431CE右键,Binary->Fill with NOPs。这时,回到程序,继续点击Again,是不是两个按钮都被隐藏了?!!哈哈哈!

    (多试几次,会发现第一个编辑框还是有字数限制的,需要大于4个)

    小结:两个按钮调用了相同的关键CALL,即使用了同一个算法函数对注册码进行验证,这要爆破这一个函数或它的跳转就行。

    4、注册机尝试

    由于两个按钮的关键Call一样,所以这个算法就很省事了,直接在 OD中跳转到CALL 004429A8的地方,F8单步分析。

    慢着,是不是很多CALL还不知道什么意思?是啊,先用IDR看一下嘛!

    在IDR中也是用Ctrl+G,输入地址 004429A8,确定:

     _CrackMe200::sub_004429A8
     004429A8    push       ebp
     004429A9    mov        ebp,esp
     004429AB    add        esp,0FFFFFFF4
     004429AE    push       ebx
     004429AF    push       esi
     004429B0    push       edi
     004429B1    mov        dword ptr [ebp-8],ecx
     004429B4    mov        dword ptr [ebp-4],edx
     004429B7    mov        edi,eax
     004429B9    mov        eax,dword ptr [ebp-8]
     004429BC    call       @LStrAddRef
     004429C1    xor        eax,eax
     004429C3    push       ebp
     004429C4    push       442A7A
     004429C9    push       dword ptr fs:[eax]
     004429CC    mov        dword ptr fs:[eax],esp
     004429CF    mov        eax,dword ptr [ebp-8]
     004429D2    call       @LStrLen
     004429D7    cmp        eax,4
    >004429DA    jle        00442A62
     004429E0    xor        ebx,ebx
     004429E2    mov        eax,dword ptr [ebp-8]
     004429E5    call       @LStrLen
     004429EA    test       eax,eax
    >004429EC    jle        00442A26
     004429EE    mov        dword ptr [ebp-0C],eax
     004429F1    mov        esi,1
     004429F6    mov        eax,dword ptr [ebp-8]
     004429F9    call       @LStrLen
     004429FE    cmp        eax,1
    >00442A01    jl         00442A20
     00442A03    mov        edx,dword ptr [ebp-8]
     00442A06    movzx      edx,byte ptr [edx+esi-1]
     00442A0B    mov        ecx,dword ptr [ebp-8]
     00442A0E    movzx      ecx,byte ptr [ecx+eax-1]
     00442A13    imul       edx,ecx
     00442A16    imul       edx,edi
     00442A19    add        ebx,edx
     00442A1B    dec        eax
     00442A1C    test       eax,eax
    <00442A1E    jne        00442A03
     00442A20    inc        esi
     00442A21    dec        dword ptr [ebp-0C]
    <00442A24    jne        004429F6
     00442A26    mov        eax,ebx
     00442A28    cdq
     00442A29    xor        eax,edx
     00442A2B    sub        eax,edx
     00442A2D    mov        ecx,0A2C2A
     00442A32    cdq
     00442A33    idiv       eax,ecx
     00442A35    mov        ebx,edx
     00442A37    mov        eax,dword ptr [ebp-4]
     00442A3A    mov        ecx,59
     00442A3F    cdq
     00442A40    idiv       eax,ecx
     00442A42    mov        ecx,eax
     00442A44    mov        eax,dword ptr [ebp-4]
     00442A47    mov        esi,50
     00442A4C    cdq
     00442A4D    idiv       eax,esi
     00442A4F    add        ecx,edx
     00442A51    inc        ecx
     00442A52    mov        dword ptr [ebp-4],ecx
     00442A55    cmp        ebx,dword ptr [ebp-4]
    >00442A58    jne        00442A5E
     00442A5A    mov        bl,1
    >00442A5C    jmp        00442A64
     00442A5E    xor        ebx,ebx
    >00442A60    jmp        00442A64
     00442A62    xor        ebx,ebx
     00442A64    xor        eax,eax
     00442A66    pop        edx
     00442A67    pop        ecx
     00442A68    pop        ecx
     00442A69    mov        dword ptr fs:[eax],edx
     00442A6C    push       442A81
     00442A71    lea        eax,[ebp-8]
     00442A74    call       @LStrClr
     00442A79    ret
    <00442A7A    jmp        @HandleFinally
    <00442A7F    jmp        00442A71
     00442A81    mov        eax,ebx
     00442A83    pop        edi
     00442A84    pop        esi
     00442A85    pop        ebx
     00442A86    mov        esp,ebp
     00442A88    pop        ebp
     00442A89    ret

    然后在OD中F8单步调试详细分析:

    004429A8  /$  55            push ebp                                 ;  // reg和again 关键Call
    004429A9  |.  8BEC          mov ebp,esp
    004429AB  |.  83C4 F4       add esp,-0xC
    004429AE  |.  53            push ebx
    004429AF  |.  56            push esi
    004429B0  |.  57            push edi
    004429B1  |.  894D F8       mov [local.2],ecx
    004429B4  |.  8955 FC       mov [local.1],edx                        ;  // edx=123321转整数
    004429B7  |.  8BF8          mov edi,eax                              ;  // edi=eax=0
    004429B9  |.  8B45 F8       mov eax,[local.2]
    004429BC  |.  E8 2712FCFF   call 00403BE8                            ;  LStrAddRef
    004429C1  |.  33C0          xor eax,eax
    004429C3  |.  55            push ebp
    004429C4  |.  68 7A2A4400   push 00442A7A
    004429C9  |.  64:FF30       push dword ptr fs:[eax]
    004429CC  |.  64:8920       mov dword ptr fs:[eax],esp
    004429CF  |.  8B45 F8       mov eax,[local.2]                        ;  bbdxf
    004429D2  |.  E8 5D10FCFF   call 00403A34                            ;  @LStrLen
    004429D7  |.  83F8 04       cmp eax,0x4
    004429DA  |.  0F8E 82000000 jle 00442A62                             ;  必须 > 4
    004429E0  |.  33DB          xor ebx,ebx                              ;  // ebx=0
    004429E2  |.  8B45 F8       mov eax,[local.2]
    004429E5  |.  E8 4A10FCFF   call 00403A34                            ;  @LStrLen
    004429EA  |.  85C0          test eax,eax
    004429EC  |.  7E 38         jle short 00442A26
    004429EE  |.  8945 F4       mov [local.3],eax
    004429F1  |.  BE 01000000   mov esi,0x1
    004429F6  |>  8B45 F8       /mov eax,[local.2]
    004429F9  |.  E8 3610FCFF   |call 00403A34                           ;  @LStrLen
    004429FE  |.  83F8 01       |cmp eax,0x1
    00442A01  |.  7C 1D         |jl short 00442A20
    00442A03  |>  8B55 F8       |/mov edx,[local.2]
    00442A06  |.  0FB65432 FF   ||movzx edx,byte ptr ds:[edx+esi-0x1]    ;  // 从第一个字符开始
    00442A0B  |.  8B4D F8       ||mov ecx,[local.2]
    00442A0E  |.  0FB64C01 FF   ||movzx ecx,byte ptr ds:[ecx+eax-0x1]    ;  // 最后一个字符
    00442A13  |.  0FAFD1        ||imul edx,ecx                           ;  // 第一个字符乘上最后一个--
    00442A16  |.  0FAFD7        ||imul edx,edi                           ;  // edi=0, 所以结果一直为0
    00442A19  |.  03DA          ||add ebx,edx                            ;  // ebx=0, 所以结果一直为0
    00442A1B  |.  48            ||dec eax                                ;  // len--
    00442A1C  |.  85C0          ||test eax,eax
    00442A1E  |.^ 75 E3         |jnz short 00442A03
    00442A20  |>  46            |inc esi
    00442A21  |.  FF4D F4       |dec [local.3]                           ;  // len--
    00442A24  |.^ 75 D0         jnz short 004429F6                      ;  // 整个循环结束,edx=0,ebx=0
    00442A26  |>  8BC3          mov eax,ebx
    00442A28  |.  99            cdq
    00442A29  |.  33C2          xor eax,edx                              ;  // eax=0,edx=0
    00442A2B  |.  2BC2          sub eax,edx
    00442A2D  |.  B9 2A2C0A00   mov ecx,0xA2C2A
    00442A32  |.  99            cdq
    00442A33  |.  F7F9          idiv ecx                                 ;  // eax/ecx
    00442A35  |.  8BDA          mov ebx,edx                              ;  // 这里以上的计算结果都一定是0
    00442A37  |.  8B45 FC       mov eax,[local.1]                        ;  // 序列号转整数,从这里开始才是有意义的计算
    00442A3A  |.  B9 59000000   mov ecx,0x59
    00442A3F  |.  99            cdq                                      ;  // edx=0
    00442A40  |.  F7F9          idiv ecx                                 ;  // eax=eax/0x59
    00442A42  |.  8BC8          mov ecx,eax                              ;  // 存储结果到ecx
    00442A44  |.  8B45 FC       mov eax,[local.1]
    00442A47  |.  BE 50000000   mov esi,0x50
    00442A4C  |.  99            cdq
    00442A4D  |.  F7FE          idiv esi                                 ;  // eax=eax/0x50, edx=eax % 0x50
    00442A4F  |.  03CA          add ecx,edx                              ;  // ecx=ecx+edx
    00442A51  |.  41            inc ecx                                  ;  // ecx++
    00442A52  |.  894D FC       mov [local.1],ecx
    00442A55  |.  3B5D FC       cmp ebx,[local.1]
    00442A58  |.  75 04         jnz short 00442A5E                       ;  // ebx等于返回值,应该为1
    00442A5A  |.  B3 01         mov bl,0x1
    00442A5C  |.  EB 06         jmp short 00442A64
    00442A5E  |>  33DB          xor ebx,ebx
    00442A60  |.  EB 02         jmp short 00442A64
    00442A62  |>  33DB          xor ebx,ebx
    00442A64  |>  33C0          xor eax,eax                              ;  // 都调到这里
    00442A66  |.  5A            pop edx
    00442A67  |.  59            pop ecx
    00442A68  |.  59            pop ecx
    00442A69  |.  64:8910       mov dword ptr fs:[eax],edx
    00442A6C  |.  68 812A4400   push 00442A81
    00442A71  |>  8D45 F8       lea eax,[local.2]
    00442A74  |.  E8 3F0DFCFF   call 004037B8                            ;  @LStrClr
    00442A79  .  C3            retn
    00442A7A   .^ E9 F907FCFF   jmp 00403278
    00442A7F   .^ EB F0         jmp short 00442A71
    00442A81   .  8BC3          mov eax,ebx                              ;  // 返回到这里
    00442A83   .  5F            pop edi
    00442A84   .  5E            pop esi
    00442A85   .  5B            pop ebx
    00442A86   .  8BE5          mov esp,ebp
    00442A88   .  5D            pop ebp
    00442A89   .  C3            retn
    

    请详细看上面的汇编代码的注释在地址00442A35以上部分的代码最终的结果一直为0,这个地址下面的代码才真正的有实际意义。

    其中,有意义这一块的C/CPP代码大概如下:

    int nCode=123321; // 用户输入的注册码,必须是4位以上,转换为整数
    int n1 = nCode/0x59;
    int n2 = nCode%0x50;
    if( n1+n2+1 == 0 )
    {
        // 第一次隐藏Register按钮,显示again按钮,第二次隐藏again按钮
    }else{
        //显示register按钮,隐藏again按钮 
    }

    为什么我没有写出一个注册机呢?

    算法原理大概是一个数除以0x59的结果加上它对于0x50取模,然后结果加上1等于0。不加1还好理解,加上1就顿时感觉蛋疼了,我实在无法找到这样一个数。(当然也不排除我理解错了,求大牛指导!!)

    007结束。

    -----------

    PS: 有人说,帖子内容很难看懂,问我能否做成视频?

    我想说:

    首先,我的贴子都是按照我分析的流程写的,相关的工具、参考资料、代码分析、关键算法分析流程 全部都已经很详细地写下来了。只要你拿着OD和有限的几个工具,除非你真的连F7、F8分析代码都不会,否则对照我的文章肯定能看到一些有价值的东西,至少我是这么认为的。

    其次,【无论多么简单的事情,想要做好,都是不容易的!】经常混论坛的都知道,爆破虽易,算法不易!确实自己水平有限,无法做到举重若轻,几分钟分析出一个算法。这种水平我真达不到!此系列文章的重头戏不在于爆破,而在于算法部分。每天破解的80%以上的时间都是在分析算法的部分,还有10%是用来整理排版帖子,虽然做的不是很好,但我问心无愧地做到了自己的承诺,尽自己所能。帖子尚且不易,视频何其远乎!我只能说声抱歉了!

    最后,谢谢大家的捧场!

    BY  笨笨D幸福

  • 相关阅读:
    Spring框架开发的三种模式
    IDEA 的Surround With快捷键
    Spring框架IOC和AOP的实现原理与详解
    mitmproxy 安装配置
    adb 使用
    小象代理
    requests 模块查看请求的ip地址
    smtplib 邮件模块
    淘宝直播数据爬取 + 淘宝模拟登陆
    postgresql基础操作
  • 原文地址:https://www.cnblogs.com/bbdxf/p/3790039.html
Copyright © 2011-2022 走看看