前言

  1. 010 Editor 是很好的逆向学习软件,通过编写注册机对提高逆向能力有很大帮助,
  2. 由于本文写的比较早,发布时已经出9.0版本,特添加9.0版本破解补丁。

一、工具及软件介绍

  • 逆向工具:x64 dbg
  • 平台:Win_1803 x64 虚拟机
  • 破解软件:010 Editor v8.0.1 x64

二、逆向分析

2.1、找到提示错误注册弹窗

  接上一篇,通过对CreateWindowExA、CreateWindowExW下断点,并且利用堆栈调用找到关键代码处

  找到弹窗中的提示字符串,选中这一行,x64dbg会自动分析出该处是从何处跳转过来的,跟踪并分析

2.2、分析跳转处代码

  到达跳转处代码,我们会发现有多组比较跳转,其中一个就是弹出无效的用户名和注册码信息处的跳转。

  通过分析推测,这几组比较是判断错误类型的。

  此时,我们选中最上方的比较处,会发现该处比较是从哪里跳转过来的,继续跟踪分析。

  来到这里我们发现ebxDB比较,结合分析得出,如果不相等就进入错误判断分支,相等则弹出注册成功弹窗。

  我们选中比较处代码,会发现跳转来源,继续跟踪分析。

  通过分析该处代码可知,E7来源于第一个CALL中,第二个CALL的返回值是用于判断注册码是否正确的,即返回结果为DB,接着往下看,当esi等于E7,即第一个CALL的返回结果为E7或者rcx + 3c等于0时都会跳转到下边注册码正确判断的流程中去。

  此时,我们得出的结论是,当第二个CALL的返回值是DB时,注册就会成功,这里我们将第二个CALL函数打上标签为=DB,方便后续分析。

  我们进入=DB这个函数分析一下

  我们已经知道,要使注册成功,这个函数就必须返回DB,通个观察这个函数,当7FF715213D46这个函数的返回值为2D时会将这个函数的返回值赋值为DB,同时,我们发现这个函数还会返回E7这个值,这时我们想到在分析=DB这个函数之前也有一个函数可能会返回为E7,我们对比一下这2个函数看看。

  我们发现这2个是同一函数,此时根据前后关系分析,当该函数的返回值为E7时会跳转到注册码正确验证处,但这个函数的返回值是E7时,=DB这个函数的返回值却不是DB

  通过这2个条件,我们得出这个函数的返回值在等于2D时,注册会成功。

  我们将该函数打上=2D标签,方便分析,同时更改之前的分析注释。

2.3、=2D 函数分析

  通过上方分析已知,该函数需要等于2D,才会注册成功。

  此时,我们先找到返回值为2D操作的代码。

  找到2D赋值处后,我们就需要跟踪调试这个函数了。

  通过单步跟踪发现00007FF71704597E之前是获取注册码和一些检测工作

2.3.1、获取注册码处分析

  • 使用的测试注册码为:0011-2233-4455-6677-8899

  • 注册码与局部变量的对应关系

    • KEY[0] = 00 KEY[1] = 11 KEY[2] = 22 KEY[3] = 33 KEY[4] = 44
    • KEY[5] = 55 KEY[6] = 66 KEY[7] = 77 KEY[8] = 88 KEY[9] = 99
  • 内存中的存储状态【RSP + 28】

  • 通过00007FF71704597E及之后的汇编代码确定数据的存储位置

    • KEY[0] = [RSP + 28]
    • KEY[1] = [RSP + 29]
    • KEY[2] = [RSP + 2A]
    • KEY[3] = [RSP + 2B]
    • KEY[4] = [RSP + 2C]
    • KEY[5] = [RSP + 2D]
    • KEY[6] = [RSP + 2E]
    • KEY[7] = [RSP + 2F]
    • KEY[8] = [RSP + 30]
    • KEY[9] = [RSP + 31]
  • 00007FF71704597E之后的代码分析

  • 通过分析发现,当取出KEY[3]的值后,有3处比较跳转,分别为9C/FC/AC,对应的C代码如下
switch ( KEY[] )
{
case 0x9C:
break;
case 0xFC:
break;
case 0xAC:
break;
}
  • 接下来就可以单独分析每一个分支了

2.3.2、3处分支分析

2.3.2.1、9C情况

  • 得到的结果为

    • EBX = ((( KEY[0] ^ KEY[6] ) ^ 0x18 ) + 0x3D ) ^ 0xA7
    • EAX = (((((( KEY[1] ^ KEY[7] ) * 0x100) + ( KEY[2] ^ KEY[5] )) ^ 0x7892 ) + 0x4d30 ) ^ 0x3421) / 0xB 或 0
  • 对应的C代码
case 0x9C:
DWORD EAX = ( ( ( ( ( ( KEY[ ] ^ KEY[ ] ) * 0x100 ) +
( KEY[ ] ^ KEY[ ] ) ) ^ 0x7892 ) + 0x4d30 ) ^ 0x3421 );
DWORD EBX = ( ( ( KEY[ ] ^ KEY[ ] ) ^ 0x18 ) + 0x3D ) ^ 0xA7;
if (EAX % 0xB != )
{
EAX = ; // error
}
if (EAX == || EAX > 0x3E8)
{
return; // error
}
if (EBX == )
{
return; // error
}
// 如果EBX >= 0x2 EBX = 0 否则不变
// EBX 做为下面用户名处理函数的参数
if ( EBX >= 0x2 )
{
EBX = ;
}
// EAX 做为下面用户名处理函数的参数
EAX = EAX / 0xB;
break;

2.3.2.2、FC情况

  • 得到的结果为

    • EBX = FF
    • EAX = 0x1
  • 由于后面的判断,如果是0xFC,是不会返回0x2D的,这里略

2.3.2.3、AC情况

  • 得到的结果为

    • EBX = EAX
    • DWORD PTR DS:[RDI+0x30] = (((((( KEY[1] ^ KEY[7] ) * 0x100) + ( KEY[2] ^ KEY[5] )) ^ 0x7892 ) + 0x4d30 ) ^ 0x3421) / 0xB 或 0
  • 对应的C代码
case 0xAC:
DWORD EAX = ( ( ( ( ( ( KEY[ ] ^ KEY[ ] ) * 0x100 ) +
( KEY[ ] ^ KEY[ ] ) ) ^ 0x7892 ) + 0x4d30 ) ^ 0x3421 );
if ( EAX % 0xB != )
{
EAX = ; // error
}
if ( EAX == || EAX > 0x3E8 )
{
return; // error
}
DWORD ECX = ( ( ( ( ( ( ( KEY[ ] ^ KEY[ ] ) << 0x8 ) + ( ( KEY[ ] ^ KEY[ ] ) << 0x10 ) + ( KEY[ ] ^ KEY[ ] ) ) ^ 0x5B8C27 ) ^ 0x22C078 ) - 0x2C175 ) ^ 0xFFE53167 ) & 0xFFFFFF; EAX = 0xF0F0F0F1;
DWORD EDX = ;
// 伪代码:EDX : EAX = EAX * ECX
EDX = EDX >> 0x4;
EAX = EDX * 0x11;
ECX = ECX - EAX;
if (ECX == ) // ECX = EAX
{
EAX = EDX; // Right
}
else
{
EAX = ;
}
DWORD RDI0x30 = EAX / 0xB;
EBX = EAX;
break;

2.3.3、用户名处理函数

2.3.3.1、函数调用处分析

  • 上面已经准备好了 EBXRDI + 30的值
  • 结合IDA分析得出,用户名处理函数的参数如下:
    • 参数一:用户名字符串首地址
    • 参数二:如果类型是0xFC就是0,否则是1,用于函数内部判断类型
    • 参数三:准备好的EBX
    • 参数四:准备好的RDI + 30

2.3.3.2、函数内部分析

void function( char* name )
{
DWORD KEY[ ] = { 0x9C };
DWORD EBX = ;
DWORD RDI30 = ;
DWORD LOCAL1 = ;
DWORD LOCAL2 = ( EBX/*参数3*/ * 0x11 ) & 0xFF;
DWORD LOCAL3 = ;
DWORD LOCAL4 = ;
DWORD ESI = RDI30/*参数4*/ * 0xF;
int NameLen = strlen( name );
char EAX[ ] = { }; // 函数返回值
DWORD PW[ ] = {
0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821,
…………
0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };
for ( int i = ; i < NameLen; i++ )
{
char nameChar = toupper( name[ i ] );
if ( KEY[ ] != 0xFC )
{
LOCAL1 = ( PW[ nameChar ] ^ PW[ nameChar + 0xD ] ) * PW[ nameChar + 0x2F ]
+ PW[ LOCAL2 ]
+ PW[ ESI ]
+ PW[ LOCAL3 ];
}
else
{
LOCAL1 = ( PW[ nameChar ] ^ PW[ nameChar + 0x3F ] ) + PW[ nameChar + 0x17 ]
+ PW[ LOCAL2 ]
+ PW[ ESI ]
+ PW[ LOCAL4 ];
}
LOCAL3 += 0x13;
LOCAL2 += 0x9;
ESI += 0xD;
LOCAL4 += 0x7;
}
*( DWORD* ) EAX = LOCAL1;
}

2.3.4、用户名处理函数返回值及剩余代码分析

  • 通过分析发现,当KEY[3] = 0xFC时,不会跳转到正确的返回值赋值处
  • 所以,,当KEY[3] = 0xFC时,之后的代码都不用分析
  • 对应C代码如下
void function1()
{
DWORD KEY[ ] = { };
DWORD EAX[ ] = { };
if ( KEY[ ] == EAX[ ] &&
KEY[ ] == EAX[ ] &&
KEY[ ] == EAX[ ] &&
KEY[ ] == EAX[ ] )
{
switch ( KEY[] )
{
case 0x9C:
/*
正确
*/
break;
case 0xFC:
/*
错误
*/
break;
case 0xAC:
/*
正确
*/
break;
}
}
}

三、注册机编写

  • 本次使用MFC编写注册机
  • 全局数组密码表(内存中提取)
DWORD PW[  ] = {
0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821,
0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60,
0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA,
0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B,
0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971,
0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08,
0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E,
0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F,
0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9,
0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99,
0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A,
0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C,
0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A,
0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851,
0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF,
0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60,
0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2,
0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72,
0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C,
0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D,
0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423,
0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B,
0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1,
0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2,
0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C,
0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC,
0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E,
0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F,
0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E,
0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5,
0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03,
0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945
};
  • 获取随机数小于0x3E8的函数(获取注册人数)
DWORD GetRandNum() {
DWORD Result;
srand( ( unsigned ) time( NULL ) );
return Result = rand() % 0x3E8; // 用于获取随机区间,(0, 3E8],为注册人数 1 ~ 1000
}
  • 用户名处理函数

    • 参数1:用户名
    • 参数2:注册人数(随机函数获取)
    • 参数3:注册天数(当版本注册【0x9C】时 = 0,当时间注册时【0xAC】时=要注册的年月日 - 1970.1.1之间的天数)
void CKeyGenDlg::GetEncryStr( char * szName, DWORD Regmen, DWORD day )
{
DWORD ESI = Regmen * 0xF;
DWORD LOCAL1 = ;
DWORD LOCAL2 = ( day * 0x11 ) & 0xFF;
DWORD LOCAL3 = ;
//DWORD LOCAL4 = 0;
BYTE EAX[ ] = { };
int NameLen = strlen( szName );
for ( int i = ; i < NameLen; i++ )
{
char nameChar = toupper( szName[ i ] );
LOCAL1 =
( ( ( LOCAL1 + PW[ nameChar ] ) ^ PW[ ( nameChar + 0xD ) & 0xFF ] )*PW[ ( nameChar + 0x2F ) & 0xFF ] )
+ PW[ LOCAL2 ]
+ PW[ ESI & 0xFF ]
+ PW[ LOCAL3 ]; ESI += 0xD;
LOCAL2 += 0x9;
LOCAL3 += 0x13;
}
*( DWORD* ) EAX = LOCAL1;
KEY[ ] = EAX[ ];
KEY[ ] = EAX[ ];
KEY[ ] = EAX[ ];
KEY[ ] = EAX[ ];
}
  • 注册码计算函数

    • 参数1:用户名
    • 参数2:注册天数
  • 通过该函数可以根据用户名计算出注册码,同时可计算版本注册及天数注册(按选择不同区分)
void CKeyGenDlg::CalcReg( char * szName, DWORD day )
{
char destbuff[ ] = { };
DWORD Regmen = GetRandNum();
/*
判断是否整除函数的结果为:Regmen
对应公式为:Regmen = ((((( KEY[1] ^ KEY[7] ) * 0x100 + ( KEY[2] ^ KEY[5] )) ^ 0x7892 ) + 0x4D30 ) ^ 0x3421) / 0xB
逆向计算得出:( KEY[1] ^ KEY[7] ) * 0x100 + ( KEY[2] ^ KEY[5] ) 的值,WORD
*/
WORD tmp = ( ( ( Regmen * 0xB ) ^ 0x3421 ) - 0x4D30 ) ^ 0x7892; USES_CONVERSION;
if ( status )
{
//MessageBox( L"版本", 0, 0 );
KEY[ ] = 0x9C;
day = ; // 当为版本注册时,天数必须为0
GetEncryStr( szName, Regmen, day );
KEY[ ] = ( HIBYTE( tmp ) ) ^ KEY[ ];
KEY[ ] = ( LOBYTE( tmp ) ) ^ KEY[ ];
/*
版本号 9 < ((( KEY[0] ^ KEY[6] ) ^ 0x18 ) + 0x3D ) ^ 0xA7
这里取 0x18
*/
KEY[ ] = ( ( ( 0x18 ^ 0xA7 ) - 0x3D ) ^ 0x18 ) ^ KEY[ ];
sprintf_s( destbuff, "%02X%02X-%02X%02X-%02X%02X-%02X%02X", KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ] );
m_Reg = A2T( destbuff );
UpdateData( FALSE );
}
else
{
//MessageBox( L"天数", 0, 0 );
KEY[ ] = 0xAC;
GetEncryStr( szName, Regmen, day );
KEY[ ] = ( HIBYTE( tmp ) ) ^ KEY[ ];
KEY[ ] = ( LOBYTE( tmp ) ) ^ KEY[ ];
// 通过天数逆向推导得出计算之前的数值
/*
day = ((((((( KEY[9] ^ KEY[5] ) << 0x10 ) + (( KEY[4] ^ KEY[8] ) << 0x8 ) + KEY[0] ^ KEY[6])xor 005B8C27)
xor 0x22c078) - 0x2C175) xor 0xFFE53167) and 0xFFFFFF
*/
DWORD tmp2 = ( ( ( ( day * 0x11 ) ^ 0xFFE53167 ) + 0x2C175 ) ^ 0x22C078 ) ^ 0x5B8C27;
KEY[ ] = ( tmp2 & 0xFF ) ^ KEY[ ];
KEY[ ] = ( ( tmp2 >> 0x8 ) & 0xFF ) ^ KEY[ ];
KEY[ ] = ( ( tmp2 >> 0x10 ) & 0xFF ) ^ KEY[ ];
sprintf_s( destbuff, "%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ], KEY[ ] );
m_Reg = A2T( destbuff );
UpdateData( FALSE );
}
}
  • 按钮响应函数
  • 该函数对运算逻辑及数据进行处理,当用户名不为空时,计算注册码
void CKeyGenDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
// CDialogEx::OnOK();
memset( KEY, , sizeof( KEY ) ); // 清空数组
UpdateData( TRUE );
if ( !m_User.IsEmpty() )
{
USES_CONVERSION;
char * szName = T2A( m_User );
DWORD day = 0x7224; // 1970.1.1 - 指定日期的天数
CalcReg( szName, day );
}
else
{
MessageBox( _T( "用户名不能为空" ), , MB_ICONWARNING );
}
}

3.1、注册机外观

由于使用了单选控件,于是在选择授权方式时对注册码编辑框进行处理

3.2、结果验证

3.2.1、版本授权

3.2.2、天数授权

四、网络验证

4.1、两处判断网络验证是否通过处

  • 第一处

  • 第二处

总结:当RCX + 3C处的值为0时,走正常流程,否则,使用注册机注册的将会提示注册码无效。

继续观察第一处,在网络验证处下方有一个函数,我们进去浏览会发现网址拼接,网址拼接中会发现有namepwd字样,此时怀疑该函数可能就是修改RCX + 3C处的值的函数。

4.2、确认是否为网络验证函数

  • 可以通过新建虚拟机或修改RCX + 3C处的值为0,通过修改ZF标志位强制执行该函数,验证结果如下

4.3、突破网络验证

  • 方法一:将两处网络验证比较处的跳转进行修改,即JEJMP,使其强制执行网络验证通过后的代码
  • 方法二:进入网络验证函数在其函数头直接RET将函数返回,不对RCX + 3C进行修改

总结:突破网络验证的方法有很多,还需要多学习。

五、附件

010 Editor 8.0.1  提取码:d6ds

010 Editor 9.0     提取码:0lfe

注册机

六、源码

说明:移植MFC部分代码,使用Qt重写,并为时间注册添加自选时间功能

GitHub:KenGen

 

010 Editor 8.0.1 之 逆向分析及注册机编写的更多相关文章

  1. 010 Editor v8.0.1(32 - bit) 算法逆向分析、注册机编写

    010 Editor 的逆向分析整体算下来还是比较简单的,将程序拖入OD,通过字符串搜索定位到核心代码,经过分析,主要是如下图所示的两个关键函数,返回正确的值,才算是注册成功. 00409C9B 这个 ...

  2. 010 Editor 8.0.1 之 暴力破解

    一.工具及软件介绍二.破解1.打开调试程序2.打开注册页面3.在弹出窗口API中下断4.点击注册按钮5.逐一进去观察6.找到正确的授权字符串7.找到函数头8.找到计算出EBX的CALL9.进入函数跟踪 ...

  3. [转]Wing IDE 6.0 安装及算号器注册机代码

    下载安装wing 选择第三个,运行算号器,输入license id 输入request id. Python 2 算号器注册机代码 import string import random import ...

  4. Navicat Premium 15.0.17 破解激活(DFoX 注册机)

    Navicat Premium v15.0.17 安装程序和注册机已放入百度网盘,下载地址在本文最后 1. 下载并安装 Navicat Premium 15 在官网下载 Windows 版本的 Nav ...

  5. 深入底层逆向分析TDC‘s keygenme(手脱压缩壳)

    系统 : Windows xp 程序 : TDC‘s keygenme 程序下载地址 :http://pan.baidu.com/s/1gdWyt6z 要求 : 脱壳 & 注册机编写 使用工具 ...

  6. [应用软件] VMware Workstation 12.0.0 Pro 正式版下载【附注册机+注册码】

    软件信息 软件名称: VMware Workstation 软件版本: 12 软件大小: 300 MB 软件语言: 简体中文 更新时间: - 软件授权: 免费 软件类别: 安装版 运行环境: WinX ...

  7. IM通信协议逆向分析、Wireshark自定义数据包格式解析插件编程学习

    相关学习资料 http://hi.baidu.com/hucyuansheng/item/bf2bfddefd1ee70ad68ed04d http://en.wikipedia.org/wiki/I ...

  8. C++反汇编与逆向分析技术揭秘

    C++反汇编-继承和多重继承   学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的 ...

  9. Android逆向分析(2) APK的打包与安装背后的故事

    前言 上一次我们反编译了手Q,并遇到了Apktool反编译直接crash的问题,虽然笔者很想在这次解决这个问题,但在解决途中,发现该保护依赖于很多知识,所以本次先插入一下,正所谓知其然知其所以然,授之 ...

随机推荐

  1. group by 拓展

    Oracle的group by除了基本使用方法以外,还有3种扩展使用方法,各自是rollup.cube.grouping sets.分别介绍例如以下: 1.rollup 对数据库表emp.如果当中两个 ...

  2. 小程序坑之 swiper组件

    表现:swiper 内容 空白 原因:swiper组件的current值为n时,重新刷新页面,current值不变,当刷新后的swiper item的数量少于 n 时,swpier找不到对应的item ...

  3. react基础学习 一

    1. 搭建环境 安装react脚手架  >npm install create-react-app -g 创建文件            >create-react-app 项目名称 启动 ...

  4. react基础学习 二——生命周期

    生命周期mount: mounting装载创建 update更新 unmounting卸载 错误捕获 注意点:生命周期函数的 作用,什么之后用 只有类式组件有生命周期,函数式组件没有生命周期 moun ...

  5. 如何解决fiddler的响应显示乱码问题

    fiddler中Response出现乱码, 这是因为HTML被压缩了, 我们可以通过两种方法去解压.方法1:点击Response Raw上方的"Response is encoded any ...

  6. 74.纯 CSS 创作一台 MacBook Pro

    原文地址:https://segmentfault.com/a/1190000015568609 HTML code: <div class="macbook"> &l ...

  7. wdk1703+vs2015编译的诡异问题

    最近将wdk升级到1703(10.0.15063.0)版本,编译一个新建的minifiter项目居然出现了失败 提示错误为 WindowsDriver.common.targets(460,5): e ...

  8. 201772020113 李清华《面向对象程序设计(java)》第17周学习总结

    1.实验目的与要求 (1) 掌握线程同步的概念及实现技术: (2) 线程综合编程练习 2.实验内容和步骤 实验1:测试程序并进行代码注释. 测试程序1: l  在Elipse环境下调试教材651页程序 ...

  9. 201772020113 李清华《面向对象程序设计(java)》第16周学习总结

    1.实验目的与要求 (1) 掌握线程概念: (2) 掌握线程创建的两种技术: (3) 理解和掌握线程的优先级属性及调度方法: (4) 掌握线程同步的概念及实现技术: 2.实验内容和步骤 实验1:测试程 ...

  10. Windows服务器

    知道了怎么装VMware workstation并且创建虚拟机装上了系统配好网络