破解 k4n3程序(调♂教 绅(hen)士(tai) 程序猿)

系统 : Windows xp

程序 : k4n3

程序下载地址 :http://pan.baidu.com/s/1sklYrHN

要求 : 注册机编写

使用工具 : IDA Pro & OD & Hex workshop

可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“非明码比较的Crackme的破解”。

使用IDA载入程序,打开字符串表,根据“Wow you did it... Now write a valid keygen with NO ASM RIPPING :X”的字符串提示

向上翻找到关键代码,首先来看看程序是怎样约束输入字串的:

004011BF  |.  6A 45         push    45                               ; /Count = 45 (69.)
004011C1  |.  50            push    eax                              ; |Buffer
004011C2  |.  A4            movs    byte ptr es:[edi], byte ptr [esi>; |
004011C3  |.  8B3D A8404000 mov     edi, dword ptr [<&USER32.GetDlgI>; |USER32.GetDlgItemTextA
004011C9  |.  68 E8030000   push    3E8                              ; |ControlID = 3E8 (1000.)
004011CE  |.  51            push    ecx                              ; |hWnd
004011CF  |.  FFD7          call    edi                              ; \GetDlgItemTextA
004011D1  |.  8BF0          mov     esi, eax
004011D3  |.  85F6          test    esi, esi                         ;  当用户名字串长度为0
004011D5  |.  0F84 4B010000 je      00401326                         ;  出错
004011DB  |.  83FE 40       cmp     esi, 40                          ;  当用户名长度大于64时
004011DE  |.  0F87 42010000 ja      00401326                         ;  出错
004011E4  |.  8B45 08       mov     eax, dword ptr [ebp+8]
004011E7  |.  8D55 94       lea     edx, dword ptr [ebp-6C]
004011EA  |.  6A 13         push    13                               ; /Count = 13 (19.)
004011EC  |.  52            push    edx                              ; |Buffer
004011ED  |.  68 E9030000   push    3E9                              ; |ControlID = 3E9 (1001.)
004011F2  |.  50            push    eax                              ; |hWnd
004011F3  |.  FFD7          call    edi                              ; \GetDlgItemTextA
004011F5  |.  6BC0 03       imul    eax, eax, 3
004011F8  |.  C1E0 02       shl     eax, 2
004011FB  |.  05 CD000000   add     eax, 0CD                         ;  密钥长度*3再左移2位,最后加上0CDH
00401200  |.  8945 FC       mov     dword ptr [ebp-4], eax
00401203  |.  817D FC A5010>cmp     dword ptr [ebp-4], 1A5           ;  如果结果不是1A5,则跳转
0040120A  |.  0F85 BC000000 jnz     004012CC                         ;  显示密钥有误
00401210  |.  33C0          xor     eax, eax
00401212  |.  8A45 94       mov     al, byte ptr [ebp-6C]            ;  取密钥首个字母
00401215  |.  84C0          test    al, al                           ;  判断字符值是否为0
00401217  |.  74 13         je      short 0040122C
00401219  |.  8D4D 94       lea     ecx, dword ptr [ebp-6C]          ;  取密钥字串地址
0040121C  |>  3C 30         /cmp     al, 30                          ;  如果字符小于30h
0040121E  |.  0F82 C6000000 |jb      004012EA                        ;  则跳转至提示出错函数
00401224  |.  8A41 01       |mov     al, byte ptr [ecx+1]            ;  下一个字符
00401227  |.  41            |inc     ecx                             ;  循环变量自增
00401228  |.  84C0          |test    al, al                          ;  当处理到字符串结尾
0040122A  |.^ 75 F0         \jnz     short 0040121C                  ;  则退出循环

我们看到,密钥长度必须是一个固定值,否则将提示出错。经过推算,可以知道密钥长度应该是18.

这里,我们随便填写一个长度为18的密钥,例如:“123456789ABCDEF123”。让程序流程继续执行:

0040122C  |> \E8 CFFDFFFF   call    00401000                         ;  该子程序清空eax,edx,ecx寄存器的值
00401231  |.  8D85 2CFFFFFF lea     eax, dword ptr [ebp-D4]          ;  取用户名字串地址
00401237  |.  50            push    eax
00401238  |.  E8 43FEFFFF   call    00401080                         ;  拼接用户名字串和‘ is a 。。。’字串,并根据字串算出一个值

这里,程序跳转进入401080子程序,我们F7进入:

00401080  /$  55            push    ebp
00401081  |.  8BEC          mov     ebp, esp
00401083  |.  51            push    ecx
00401084  |.  53            push    ebx
00401085  |.  56            push    esi
00401086  |.  57            push    edi
00401087  |.  68 80504000   push    00405080                         ;  ASCII "eheh"
0040108C  |.  6A 00         push    0
0040108E  |.  E8 ADFFFFFF   call    00401040                         ;  通过字串eheh对eax的值做一些修改

继续F7进入子程序401040:

00401040  /$  8B4C24 04     mov     ecx, dword ptr [esp+4]
00401044  |.  56            push    esi
00401045  |.  8B7424 0C     mov     esi, dword ptr [esp+C]
00401049  |.  33C0          xor     eax, eax
0040104B  |.  33D2          xor     edx, edx
0040104D  |.  8A4431 03     mov     al, byte ptr [ecx+esi+3]
00401051  |.  8A5431 02     mov     dl, byte ptr [ecx+esi+2]
00401055  |.  C1E0 08       shl     eax, 8                           ;  左移8位
00401058  |.  03C2          add     eax, edx
0040105A  |.  33D2          xor     edx, edx
0040105C  |.  8A5431 01     mov     dl, byte ptr [ecx+esi+1]
00401060  |.  C1E0 08       shl     eax, 8
00401063  |.  03C2          add     eax, edx
00401065  |.  33D2          xor     edx, edx
00401067  |.  8A1431        mov     dl, byte ptr [ecx+esi]
0040106A  |.  5E            pop     esi
0040106B  |.  C1E0 08       shl     eax, 8
0040106E  |.  03C2          add     eax, edx
00401070  \.  C3            retn

回到401080子程序领空中,发现整个子程序多次调用了401040子程序:

00401080  /$  55            push    ebp
00401081  |.  8BEC          mov     ebp, esp
00401083  |.  51            push    ecx
00401084  |.  53            push    ebx
00401085  |.  56            push    esi
00401086  |.  57            push    edi
00401087  |.  68 80504000   push    00405080                         ;  ASCII "eheh"
0040108C  |.  6A 00         push    0
0040108E  |.  E8 ADFFFFFF   call    00401040                         ;  通过字串eheh对eax的值做一些修改
00401093  |.  83C4 08       add     esp, 8
00401096  |.  8BD8          mov     ebx, eax
00401098  |.  E8 63FFFFFF   call    00401000                         ;  该子程序清空eax,edx,ecx寄存器的值
0040109D  |.  BF 70504000   mov     edi, 00405070                    ;  ASCII " is a whore."
004010A2  |.  83C9 FF       or      ecx, FFFFFFFF                    ;  ecx=FFFFFFFF
004010A5  |.  33C0          xor     eax, eax
004010A7  |.  F2:AE         repne   scas byte ptr es:[edi]           ;  扫描es:[edi]中的字串,循环次数ecx,找到与al相同的值则停止
004010A9  |.  F7D1          not     ecx                              ;  执行完这条语句ecx=‘is a 。。’字串长度+1
004010AB  |.  2BF9          sub     edi, ecx                         ;  重新指向字串首地址
004010AD  |.  8BF7          mov     esi, edi
004010AF  |.  8B7D 08       mov     edi, dword ptr [ebp+8]           ;  edi指向用户名字串
004010B2  |.  8BD1          mov     edx, ecx                         ;  edx=‘is a 。。’字串长度+1
004010B4  |.  83C9 FF       or      ecx, FFFFFFFF
004010B7  |.  F2:AE         repne   scas byte ptr es:[edi]           ;  扫描es:[edi]中的字串,循环次数ecx,找到与al相同的值则停止
004010B9  |.  8BCA          mov     ecx, edx                         ;  edx= ‘is a。。。’字串的长度+1
004010BB  |.  4F            dec     edi                              ;  此时es:[edi]指向字串结尾
004010BC  |.  C1E9 02       shr     ecx, 2                           ;  ecx右移两位
004010BF  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>;  拼接字串
004010C1  |.  8BCA          mov     ecx, edx
004010C3  |.  83E1 03       and     ecx, 3                           ;  ecx=1
004010C6  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>;  加上结尾
004010C8  |.  33FF          xor     edi, edi
004010CA  |.  33F6          xor     esi, esi
004010CC  |>  8B45 08       /mov     eax, dword ptr [ebp+8]          ;  将拼接好的字串地址放入eax
004010CF  |.  50            |push    eax
004010D0  |.  56            |push    esi
004010D1  |.  E8 6AFFFFFF   |call    00401040                        ;  通过入栈的字串对eax的值做一些修改
004010D6  |.  8B8E 30504000 |mov     ecx, dword ptr [esi+405030]
004010DC  |.  83C4 08       |add     esp, 8                          ;  平衡堆栈
004010DF  |.  33CF          |xor     ecx, edi                        ;  ecx与edi异或
004010E1  |.  03C1          |add     eax, ecx                        ;  eax再加上ecx
004010E3  |.  8945 FC       |mov     dword ptr [ebp-4], eax          ;  保存eax
004010E6  |.  C145 FC 07    |rol     dword ptr [ebp-4], 7            ;  将结果循环左移7次,每次从最高位(最左)移出的数据位都补充到最低位
004010EA  |.  8B45 FC       |mov     eax, dword ptr [ebp-4]          ;  再赋给eax
004010ED  |.  83C6 04       |add     esi, 4                          ;  循环变量+4
004010F0  |.  33D8          |xor     ebx, eax                        ;  ebx^eax
004010F2  |.  47            |inc     edi
004010F3  |.  83FE 40       |cmp     esi, 40
004010F6  |.^ 7C D4         \jl      short 004010CC
004010F8  |.  5F            pop     edi
004010F9  |.  8BC3          mov     eax, ebx                         ;  保存ebx的值
004010FB  |.  5E            pop     esi
004010FC  |.  5B            pop     ebx
004010FD  |.  8BE5          mov     esp, ebp
004010FF  |.  5D            pop     ebp
00401100  \.  C3            retn

这里,连接字串后,我们的用户名居然和“is a whore”连接在了一起!。。。翻译过来就是“看雪是个妓女”。

突然明白了《加密与解密》中为什么一直用固定格式的用户名进行测试了(┬_┬)

我x,这程序员好绅(hen)士(tai)啊!!

这里暂且忍下,等完全破解了他的算法再好好调♂教一番。

我们继续回来,看看接下来的流程:

0040123D  |.  8945 FC       mov     dword ptr [ebp-4], eax           ;  保存eax
00401240  |.  E8 BBFDFFFF   call    00401000                         ;  清空eax,edx,ecx寄存器的值
00401245  |.  8D8D 2CFFFFFF lea     ecx, dword ptr [ebp-D4]          ;  取拼接字串地址
0040124B  |.  56            push    esi
0040124C  |.  51            push    ecx
0040124D  |.  E8 BEFDFFFF   call    00401010                         ;  删去添加字串。
00401252  |.  83C4 0C       add     esp, 0C                          ;  平衡堆栈
00401255  |.  33C9          xor     ecx, ecx
00401257  |>  8B45 FC       /mov     eax, dword ptr [ebp-4]          ;  取401080子程序中计算的值
0040125A  |.  33D2          |xor     edx, edx                        ;  清零
0040125C  |.  BE 1A000000   |mov     esi, 1A
00401261  |.  F7F6          |div     esi
00401263  |.  8A9415 10FFFF>|mov     dl, byte ptr [ebp+edx-F0]       ;  根据除法余数来取子密钥
0040126A  |.  88540D C8     |mov     byte ptr [ebp+ecx-38], dl       ;  并保存
0040126E  |.  8B45 FC       |mov     eax, dword ptr [ebp-4]          ;  取401080子程序中计算的值
00401271  |.  C1E0 03       |shl     eax, 3                          ;  左移3位
00401274  |.  BA 45230100   |mov     edx, 12345
00401279  |.  F7E8          |imul    eax
0040127B  |.  03C2          |add     eax, edx
0040127D  |.  8945 FC       |mov     dword ptr [ebp-4], eax          ;  保存
00401280  |.  41            |inc     ecx                             ;  循环变量自增
00401281  |.  83F9 12       |cmp     ecx, 12
00401284  |.^ 72 D1         \jb      short 00401257
00401286  |.  E8 75FDFFFF   call    00401000                         ;  该子程序清空eax,edx,ecx寄存器的值
0040128B  |.  33C0          xor     eax, eax                         ;  在此之前的指令不对用户输入的密钥做操作 ↑

至此,对于用户名字串的操作就结束了,接下来的是密钥处理:

0040128D  |> /8A4C05 94     /mov     cl, byte ptr [ebp+eax-6C]       ;  迭代用户输入的密钥
00401291  |. |8A5405 C8     |mov     dl, byte ptr [ebp+eax-38]       ;  取之前算出的子密钥
00401295  |. |80E9 30       |sub     cl, 30
00401298  |. |32D1          |xor     dl, cl
0040129A  |. |885405 C8     |mov     byte ptr [ebp+eax-38], dl       ;  结果存回子密钥
0040129E  |. |40            |inc     eax                             ;  循环变量自增
0040129F  |. |83F8 12       |cmp     eax, 12
004012A2  |.^\72 E9         \jb      short 0040128D
004012A4  |.  E8 57FDFFFF   call    00401000                         ;  该子程序清空eax,edx,ecx寄存器的值
004012A9  |.  8D55 C8       lea     edx, dword ptr [ebp-38]          ;  取子密钥
004012AC  |.  52            push    edx
004012AD  |.  E8 5EFEFFFF   call    00401110                         ;  对子密钥进行操作

F7进入查看:

00401110  /$  8B4C24 04     mov     ecx, dword ptr [esp+4]           ;  取子密钥
00401114  |.  33C0          xor     eax, eax                         ;  清零
00401116  |>  8A1408        /mov     dl, byte ptr [eax+ecx]          ;  迭代子密钥
00401119  |.  32D0          |xor     dl, al                          ;  与循环变量异或
0040111B  |.  881408        |mov     byte ptr [eax+ecx], dl          ;  再存回去
0040111E  |.  40            |inc     eax                             ;  循环变量自增
0040111F  |.  83F8 12       |cmp     eax, 12
00401122  |.^ 72 F2         \jb      short 00401116
00401124  \.  C3            retn

返回后,程序将操作结果与固定值进行对比:

004012B2  |.  E8 49FDFFFF   call    00401000                         ;  该子程序清空eax,edx,ecx寄存器的值
004012B7  |.  8D45 C8       lea     eax, dword ptr [ebp-38]          ;  取子密钥
004012BA  |.  68 14514000   push    00405114                         ;  ASCII "KEYGENNING4NEWBIES"
004012BF  |.  50            push    eax
004012C0  |.  E8 6BFEFFFF   call    00401130                         ;  最终处理结束的子密钥是否等于固定密钥?
004012C5  |.  83C4 0C       add     esp, 0C                          ;  平衡堆栈
004012C8  |.  85C0          test    eax, eax
004012CA  |.  75 3C         jnz     short 00401308
004012CC  |>  8B4D 08       mov     ecx, dword ptr [ebp+8]
004012CF  |.  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004012D1  |.  68 0C514000   push    0040510C                         ; |Title = "Error"
004012D6  |.  68 FC504000   push    004050FC                         ; |Text = "Bad Serial :o("
004012DB  |.  51            push    ecx                              ; |hOwner
004012DC  |.  FF15 AC404000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
004012E2  |.  5F            pop     edi
004012E3  |.  33C0          xor     eax, eax
004012E5  |.  5E            pop     esi
004012E6  |.  8BE5          mov     esp, ebp
004012E8  |.  5D            pop     ebp
004012E9  |.  C3            retn
004012EA  |>  8B55 08       mov     edx, dword ptr [ebp+8]
004012ED  |.  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004012EF  |.  68 0C514000   push    0040510C                         ; |Title = "Error"
004012F4  |.  68 FC504000   push    004050FC                         ; |Text = "Bad Serial :o("
004012F9  |.  52            push    edx                              ; |hOwner
004012FA  |.  FF15 AC404000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00401300  |.  5F            pop     edi
00401301  |.  33C0          xor     eax, eax
00401303  |.  5E            pop     esi
00401304  |.  8BE5          mov     esp, ebp
00401306  |.  5D            pop     ebp
00401307  |.  C3            retn
00401308  |>  8B55 08       mov     edx, dword ptr [ebp+8]
0040130B  |.  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040130D  |.  68 F4504000   push    004050F4                         ; |Title = "Great !"
00401312  |.  68 B0504000   push    004050B0                         ; |Text = "Wow you did it... Now write a valid keygen with NO ASM RIPPING :X"
00401317  |.  52            push    edx                              ; |hOwner
00401318  |.  FF15 AC404000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA

至此,程序的整个加密, 比对流程已经分析完毕了。我们看到,此程序采用是的F(用户名)=F(函数)的形式进行加密,

也就是非明码比较。对于这种形式我们先将F(用户名)翻译成高级语言,再写出F(函数)的逆算法,就可以写出注册机。

废话不多说,马上复制一份http://www.cnblogs.com/ZRBYYXDM/p/5002789.html中搭建的MFC窗口程序,添加如下函数:

unsigned int CSerialNumber_KeygenDlg::F1040( unsigned char* str,int num )
{
    unsigned int eax = str[3+num];
    unsigned int edx = str[2+num];

    eax = eax << 8;
    eax += edx;
    edx = str[1+num];
    eax = eax << 8;
    eax += edx;
    edx = str[num];
    eax = eax << 8;
    eax += edx;

    return eax;
}

并修改OnOk函数如下:

void CSerialNumber_KeygenDlg::OnOK()
{
    // TODO: Add extra validation here
    CString str;
    GetDlgItem( IDC_EDIT_NAME )->GetWindowText( str );        //获取用户名

    int len = str.GetLength();                                //获取长度

    if ( len == 0 || len > 64 )
        MessageBox( "用户名必须长度不等于3、不高于64!" );
    else
    {
        unsigned int Veax = 0;
        CString IAW = " is a whore.";
        unsigned char link[64 + 13] = {0};                //用户名最大程度+IAW长度
        DWORD table[16] = {                                //异或常量表
            0x12,0x5C,0x34,0x22,
            0xAB,0x9D,0x54,0x00,
            0xDD,0x84,0xAE,0x66,
            0x31,0x78,0x73,0xCF
        };

        str += IAW;
        memcpy( link,str,str.GetLength() );                    //不复制结束符。

        int i = 0;
        unsigned int Vecx = 0,Vedi = 0,Vebx= F1040( (unsigned char*)"eheh",0 );
        for ( i = 0 ; i != 16 ; i++,Vedi++ ){
            Veax = F1040( link,i*4 );
            Vecx = table[i];                            //逐个取出进行异或。
            Vecx ^= Vedi;
            Veax += Vecx; 

            __asm {
                push eax
                mov eax,Veax
                rol eax,7
                mov Veax,eax
                pop eax
            }
            Vebx ^= Veax;
        }
        Veax = Vebx;
        str = str.Left( len );                            //还原用户名

        CString subkey = "";                                //密钥
        CString subkeytable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";    //子密钥
        unsigned int Temp = Veax;        

        for ( i = 0 ; i != 18 ; i++ ){
            Temp = Veax;
            Temp %= 0x1A;
            subkey += subkeytable[(int)Temp];
            Temp = Veax << 3;
            __asm {
                push eax
                push edx
                mov eax,Temp
                imul eax
                add eax,edx
                mov Temp,eax
                pop edx
                pop eax
            }
            Veax = Temp;
        }
        /*接下来先模拟F(密钥)函数的步骤,再根据这些步骤写出F(密钥)的逆算法

        CString key = "123456789ABCDEF123";                                //模拟一个输入的密钥。
        for ( i = 0 ; i != key.GetLength() ; i++ ){
            key.SetAt( i,( key.GetAt( i ) - 0x30 ) );
            subkey.SetAt( i,( subkey[i] ^ key[i] ^ i ) );
        }

        if ( subkey == "KEYGENNING4NEWBIES" )                            //如果算出的subkey值与一个固定的字串相等,则注册成功
            MessageBox( "done." );
        */

        CString Truekey;
        CString key= "KEYGENNING4NEWBIES";

        for ( i = 0 ; i != key.GetLength() ; i++ ){
            key.SetAt( i,( key[i] ^ subkey[i] ^ i ) );
            Truekey += ( key.GetAt( i ) + 0x30 );
        }

        GetDlgItem( IDC_EDIT_Number )->SetWindowText( Truekey );
    }

    //CDialog::OnOK();                    //屏蔽基类OnOk函数
}

再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("k4n3_Keygen"));

运行效果:

太棒了!我们终于写出了注册机!

那么,今天的工作就到这里结束咯!

那怎么可能呢,我们还要好好调♂教 作者一下~(乖♂乖♂站♂好♂)

首先,用hex workshop打开程序,搜索“ is a whore.”字串,并用“ is my dad!!”替换并保存:

选择是,将改动保存至文件。

再用OD载入程序,在401238处下断。输入“pediy”,“123456789ABCDEF123”,单击check:

此时堆栈界面如图示:

2333333333333

别急,还可以有更多变化。例如:

更多姿势请自行解锁。。。

时间: 2024-10-09 21:27:00

破解 k4n3程序(调♂教 绅(hen)士(tai) 程序猿)的相关文章

柯南君:教你如何对待大型网站平台的性能优化? 之 二--- 应用程序调优 (长篇总结)

柯南君:教你如何对待大型网站平台的性能优化? 之 "二"--- 应用程序调优(长篇总结) 柯南君 上一章 <柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法.指标.工具.定位)>讲到了一些测试方法.测试指标.以及测试工具.稍微讲了一些如何定位的方法?这一章主要讲一下"如何优化应用程序,将其性能提升". 一.基本知识  1.下面讲一些JAVA 程序性能方面的一些看法,首先给大家讲一下应用程序调优,需要调优哪些项? ① 运算的性能 : 看哪一个算法

InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET程序)

原文:InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET程序) InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET Framework进去) 本文转自“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=23892 从Visual Studio 2012开始,微软就把自家原来的安装与部署工具彻底废掉了,

【Spark深入学习 -14】Spark应用经验与程序调优

----本节内容------- 1.遗留问题解答 2.Spark调优初体验 2.1 利用WebUI分析程序瓶颈 2.2 设置合适的资源 2.3 调整任务的并发度 2.4 修改存储格式 3.Spark调优经验 3.1 Spark原理及调优工具 3.2 运行环境优化 3.2.1 防止不必要的分发 3.2.2 提高数据本地性 3.2.3 存储格式选择 3.2.4 选择高配机器 3.3 优化操作符 3.3.1 过滤操作导致多小任务 3.3.2 降低单条记录开销 3.3.3 处理数据倾斜或者任务倾斜 3.

程序员教流浪汉编程,开发APP

panpan @ 2013.10.05 , 09:34 am 一天,Patrick McConlogue宣布他将要教一个流浪汉学Java语言,帮助他开发一个属于他自己的app.今年23岁的Patrick是一名软件工程师,每天在去上班的路上他都会遇见那个流浪汉,然后他就决定践行自己的一个主意,看看他会不会是那个人. “这个主意很简单.”Patrick在自己的网站上写道: 1.我明天再路过时给你100美元.2.我明天再路过时给你三本JavaScript教程(入门级.高级.专家级)和一台便宜的笔记本.

橡皮鸭程序调试法

摘自:http://coolshell.cn/ 让我来为你介绍一个程序调试大法——“橡皮鸭程序调试法”,这个方法在调试界是很出众的,实施起来相当方便和简易,几乎可以随时随地地实验,几乎不需要借助任何的软件和硬件的支持,你甚至可以把你的程序打印出来,在纸面上进行调试. 那么,为什么这个方法要叫做橡皮鸭呢?因为橡皮鸭子是西方人在泡澡时最喜欢玩的一个小玩具,所以,这个东西应该家家户户都必备的.因为,这个方法由西方人发明,所以,就被取名为“橡皮鸭”了. 好了,话不多说,下面是整个调试方法的流程. 找一个

资深Python程序员教你统计,三国中人物名字出现的频率,很简单

资深Python程序员教你简单.有趣的程序:使用第三方库jieba切分,统计统计名著三国演义中人物名字出现次数. 资深Python程序员教你统计,三国中人物名字出现的频率,很简单其中一个jieba库是一个对中文文本依照汉字间关联概率进行词组划分的第三方库,使用简单,且非常好用 import jieba def getWords(): txt = open('novels/threekingdoms.txt', 'r', encoding = 'utf-8').read() words = jie

“深入简出”好程序员教你MapReduce全过程

欲说MapReduce,好程序员要和大家先讲一对概念——移动数据和移动计算. 在学习大数据的时候,我们便会接触移动数据和移动计算,这两种联系紧密而又有很大不同的概念,其中移动计算也叫做本地计算. 在以前的数据处理中时使用的移动数据,其实就是将需要处理的数据传输到存放不同处理数据方式逻辑的各个节点上.这样做的效率很低,特别是大数据中的数据量是很大的,至少都是GB以上,更大的是TB.PB甚至更大,而且磁盘I/O.网络I/O的效率是很低的,这样处理起来就需要很长的时间,远远不能满足我们的要求.而移动计

教你怎么客观评价程序员的水平?

有感于知乎上的一篇关于程序员以及关于智能运维的讨论.让我突然之间心有戚戚然的感觉.最近一段时间有点江郎才尽的感觉,写不了大的主题,就写点小东西吧. 我们从知乎上面引用的这段小故事开始: 1.魏文王问扁鹊家里三兄弟谁的医术最好.扁鹊回答说大哥最好,二哥次之,他自己最差.魏文王疑惑了,又问道,为什么扁鹊最有名呢?扁鹊回答说因为大哥治病的时候人没病就防止了,所以毫无名气.二哥呢,病刚起来的时候,就给治好了,大家以为只能治小病.而自己呢,能耐不够,非要到了病的很厉害了才能看出来,治起来的动静就大了.好在

【译】Yarn上常驻Spark-Streaming程序调优

作者从容错.性能等方面优化了长时间运行在yarn上的spark-Streaming作业 对于长时间运行的Spark Streaming作业,一旦提交到YARN群集便需要永久运行,直到有意停止.任何中断都会引起严重的处理延迟,并可能导致数据丢失或重复.YARN和Apache Spark都不是为了执行长时间运行的服务而设计的.但是,它们已经成功地满足了近实时数据处理作业的常驻需求.成功并不一定意味着没有技术挑战. 这篇博客总结了在安全的YARN集群上,运行一个关键任务且长时间的Spark Strea