AspectC++ Add-In for Microsoft® Visual C++®
http://www.pure-systems.com/fileadmin/downloads/acaddin/Aspectc-AddIn-Setup-010101.exe
我用的是VS2003環(huán)境
調(diào)試目標(biāo):C:\Program Files\pure-systems\AspectC++ Add-In\bin\CPPAddin.dll
工具:用OD調(diào)試,IDA+Hex-rays分析
重點(diǎn)集中在以下幾個(gè)地址
0x10008e60 彈許可文件詢(xún)問(wèn)的對(duì)話(huà)框
0x10017a20 解析xml格式的許可文件
0x10017730 貌似許可檢查的地方
這個(gè)是
0x10008e60的由Hex-ray分析出來(lái)的偽代碼,
代碼:
char __usercall sub_1000E860<al>(int a1<ebx>)
{
int ST14_4_0; // ST14_4@0
int v2; // ST10_4@1
const CHAR *v3; // eax@3
const CHAR *v4; // eax@10
int v6; // eax@2
char v7; // bl@2
char v8; // al@9
int v9; // [sp+Ch] [bp-9Ch]@1
signed int v10; // [sp+A4h] [bp-4h]@1
char v11; // [sp+10h] [bp-98h]@1
char v12; // [sp+48h] [bp-60h]@2
char v13; // [sp+2Ch] [bp-7Ch]@2
LPCSTR lpText; // [sp+14h] [bp-94h]@3
unsigned int v15; // [sp+28h] [bp-80h]@3
char v16; // [sp+64h] [bp-44h]@15
BYTE3(v9) = 0;
sub_10016AA0();
v10 = 0;
std__basic_string_char_std__char_traits_char__std__allocator_char____basic_string_char_std__char_traits_char__std__allocator_char__(&v11);
LOBYTE(v10) = 1;
v2 = a1;
while ( 1 )
{
sub_100169B0(16, (int)&v12);
LOBYTE(v10) = 2;
v6 = std__operator_(&v13, v6, "\\etc\\licence");
LOBYTE(v10) = 3;
v7 = sub_10017A20((int)&unk_10024460, v6, (int)&v11) == 0;
LOBYTE(v10) = 2;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v13);
LOBYTE(v10) = 1;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v12);
if ( !v7 )
break;
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v11,
"\nThe add-in will not work without a valid licence.\n\nInstall the licence file now?",
v2);
v3 = lpText;
if ( v15 < 0x10 )
v3 = (const CHAR *)&lpText;
if ( MessageBoxA(0, v3, "AspectC++ Add-In for Visual Studio .NET", 0x24u) != 6 )
break;
if ( !sub_1000E690() )
{
MessageBoxA(0, "Installation of licence file failed.", "AspectC++ Add-In", 0x40u);
break;
}
}
if ( byte_10024465 )
{
sub_10017730((int)&unk_10024460, 16, (int)&v11);
if ( v8 && (unsigned __int8)sub_10017520(&v11) != 1 )
{
BYTE3(v9) = 1;
}
else
{
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v11,
"\nThe add-in will not work.",
ST14_4_0);
v4 = lpText;
if ( v15 < 0x10 )
v4 = (const CHAR *)&lpText;
MessageBoxA(0, v4, "AspectC++ Add-In", 0x40u);
}
}
LOBYTE(v10) = 0;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v11);
v10 = -1;
sub_10016910((int)&v16);
return BYTE3(v9);
}
基本上可以得出默認(rèn)是分析
C:\Program Files\pure-systems\AspectC++ Add-In\etc\licence 許可文件
分析過(guò)程應(yīng)該在0x10017a20里
代碼:
char __thiscall sub_10017A20(int this, int a2, int a3)
{
int v3; // ebp@1
int v4; // esi@1
int v5; // eax@2
int v6; // eax@4
int v7; // edi@5
char result; // al@8
int v9; // ecx@1
int v10; // eax@5
int v11; // eax@6
int v12; // ST04_4@6
char v13; // bl@6
char v14; // [sp+Ch] [bp-28h]@6
signed int v15; // [sp+30h] [bp-4h]@6
v3 = a3;
v4 = this;
v9 = this + 96;
*(_DWORD *)v9 = 0;
*(_DWORD *)(v9 + 4) = 0;
*(_DWORD *)(v9 + 8) = 0;
*(_DWORD *)(v9 + 12) = 0;
*(_BYTE *)(v4 + 5) = 0;
std__basic_string_char_std__char_traits_char__std__allocator_char____operator_(v3, "Loading licence file failed.");
if ( *(_DWORD *)(a2 + 24) < 0x10u )
v5 = a2 + 4;
else
v5 = *(_DWORD *)(a2 + 4);
v6 = xmlParseFile(v5);
*(_DWORD *)v4 = v6;
if ( v6
&& (v10 = xmlDocGetRootElement(v6), v7 = v10, v10)
&& (v11 = std__basic_string_char_std__char_traits_char__std__allocator_char____basic_string_char_std__char_traits_char__std__allocator_char__(
&v14,
"licence"), v12 = *(_DWORD *)(v7 + 8), v15 = 0, v13 = std__operator__(v11, v12), v15 = -1, std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v14), v13)
&& sub_10017930(v7) )
{
*(_BYTE *)(v4 + 5) = 1;
sub_10017730(v4, v3, v3);
result = 1;
}
else
{
result = 0;
}
return result;
}
這是0x10017730的過(guò)程
代碼:
void __userpurge sub_10017730(int this<ecx>, int ebp0<ebp>, int a2)
{
int ST18_4_0; // ST18_4@0
int ST1C_4_0; // ST1C_4@0
int v5; // esi@1
signed int v6; // eax@4
int v7; // ST18_4@6
int v8; // eax@20
int v9; // eax@4
int v10; // ST1C_4@12
int v11; // ST1C_4@18
int r; // [sp+60h] [bp+0h]@1
int v13; // [sp+50h] [bp-10h]@1
signed int v14; // [sp+5Ch] [bp-4h]@3
char v15; // [sp+34h] [bp-2Ch]@4
char v16; // [sp+18h] [bp-48h]@4
int v17; // [sp+1Ch] [bp-44h]@12
unsigned int v18; // [sp+30h] [bp-30h]@20
int v19; // [sp+2Ch] [bp-34h]@22
v5 = this;
v13 = r ^ dword_100242D0;
std__basic_string_char_std__char_traits_char__std__allocator_char____operator_(a2, "Invalid licence file found.");
if ( *(_BYTE *)(v5 + 5) && !*(_BYTE *)(v5 + 4) )
{
sub_10017B20((int)&a2, ebp0);
v14 = 0;
if ( !sub_1001A050((int)&a2) )
{
LABEL_23:
v14 = -1;
sub_1001A060(&a2);
goto LABEL_24;
}
v9 = std__operator_(&v15, v5 + 12, v5 + 40);
LOBYTE(v14) = 1;
std__operator_(&v16, v9, v5 + 68);
LOBYTE(v14) = 3;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v15);
v6 = *(_DWORD *)(v5 + 8);
if ( v6 || !*(_DWORD *)(v5 + 96) )
{
if ( v6 == 1 && *(_DWORD *)(v5 + 96) && *(_DWORD *)(v5 + 100) && *(_DWORD *)(v5 + 104) && *(_DWORD *)(v5 + 108) )
{
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v16, "evaluation", ST18_4_0);
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v17,
*(_DWORD *)(v5 + 96),
ST1C_4_0);
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v17,
*(_DWORD *)(v5 + 100),
v10);
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v17,
*(_DWORD *)(v5 + 104),
ST1C_4_0);
v7 = *(_DWORD *)(v5 + 108);
}
else
{
if ( v6 != 2
|| !*(_DWORD *)(v5 + 96)
|| !*(_DWORD *)(v5 + 100)
|| !*(_DWORD *)(v5 + 104)
|| !*(_DWORD *)(v5 + 108) )
goto LABEL_20;
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v16, "user", ST18_4_0);
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v17,
*(_DWORD *)(v5 + 96),
ST1C_4_0);
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v17,
*(_DWORD *)(v5 + 100),
v11);
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(
&v17,
*(_DWORD *)(v5 + 104),
ST1C_4_0);
v7 = *(_DWORD *)(v5 + 108);
}
}
else
{
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v16, "beta", ST18_4_0);
v7 = *(_DWORD *)(v5 + 96);
}
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v17, v7, ST1C_4_0);
LABEL_20:
v8 = v17;
if ( v18 < 0x10 )
v8 = (int)&v17;
*(_BYTE *)(v5 + 4) = sub_10019E30(v5 + 112, v8, v19, (int)&a2);
LOBYTE(v14) = 0;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v16);
goto LABEL_23;
}
LABEL_24:
sub_1001A7B0( r ^ v13, ebp0);
}
昨天我自己調(diào)試的時(shí)候也犯了一個(gè)錯(cuò)誤,就是調(diào)試CppAddin.dll很痛苦,浪費(fèi)不少時(shí)間和分散很多的精力,中間老是受到Va_X.dll的干擾,而且msdev.exe在CppAddin沒(méi)加載時(shí)沒(méi)法直接下斷點(diǎn),必須得在OD中設(shè)置一個(gè)新模塊加載的斷點(diǎn)(選項(xiàng)->調(diào)試選項(xiàng)->事件->中斷于新模塊),這樣下來(lái),每次調(diào)試失敗后重啟的過(guò)程很是漫長(zhǎng),浪費(fèi)了不少時(shí)間,發(fā)帖子的求助的時(shí)候,我為了大大們給我能方便的解決問(wèn)題,盡量把非技術(shù)問(wèn)題都試驗(yàn)了一下,以免大大們被這些問(wèn)題困住了,一怒之下不給我管我了。但是這樣一來(lái),也為我自己解決和發(fā)現(xiàn)問(wèn)題加快了速度。
總結(jié)一下:
1.解決問(wèn)題要東方不亮,西方亮,不要將自己精力消耗在遠(yuǎn)離問(wèn)題本身的地方
2.堅(jiān)持就是勝利,哪怕是菜鳥(niǎo),不懂多少匯編(看代碼還得靠偉大、光榮、正確的F5),也能取得成績(jī)
下面寫(xiě)寫(xiě)分析過(guò)程:
其實(shí)昨天已經(jīng)找到了關(guān)鍵的過(guò)程,那就是0x10017a20,這里面就是分析xml格式的許可文件
這里面有兩個(gè)調(diào)用,sub_10017930()和 sub_10017730()
大概可以看得出來(lái),sub_10017930參與了xml格式的許可數(shù)據(jù)的解析過(guò)程,它調(diào)用成功之后,才調(diào)用10017730對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,要分析許可數(shù)據(jù)格式,必須研究10017930
代碼:
char __stdcall sub_10017930(int a1)
{
int v1; // ebp@1
int v2; // esi@1
int v3; // esi@3
char result; // al@7
int v5; // eax@1
int v6; // eax@2
char v7; // bl@2
char v8; // [sp+Ch] [bp-28h]@2
signed int v9; // [sp+30h] [bp-4h]@2
v1 = a1;
v5 = xmlGetProp(a1, "version");
v2 = v5;
if ( v5
&& (v6 = std__basic_string_char_std__char_traits_char__std__allocator_char____basic_string_char_std__char_traits_char__std__allocator_char__(
&v8,
L"1"), v9 = 0, v7 = std__operator__(v6, v2), v9 = -1, std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v8), v7) )
{
v3 = *(_DWORD *)(v1 + 12);
result = (unsigned __int8)sub_10016D60(*(_DWORD *)(v1 + 12))
&& (unsigned __int8)sub_10016E70(v3)
&& (unsigned __int8)sub_10017570(v3)
&& (unsigned __int8)sub_100172C0(v3);
}
else
{
result = 0;
}
return result;
}
在這里面取了xml的一個(gè)屬性值version,并且還有四個(gè)都不能失敗的過(guò)程:
10016d60 取product 元素
10016e70 取creation 元素
10017570 取type元素
100172c0 取signature元素
為了熟悉libxml,我特意編寫(xiě)了一段典型libxml用法,并分析了其反向工程后的代碼,
代碼:
xmlDocPtr doc = NULL;
xmlNodePtr cur = NULL;
string filename("test.xml");
doc = xmlParseFile(filename.c_str());
cur = xmlDocGetRootElement(doc);
if (xmlStrcmp(cur->name, BAD_CAST "licence"))
{
fprintf(stderr,"document of the wrong type, root node != mail");
xmlFreeDoc(doc);
/*return -1; */
}
cur = cur->xmlChildrenNode;
xmlNodePtr propNodePtr = cur;
while(cur != NULL)
{
//¨¨?3??¨²¦Ì??D¦Ì??¨²¨¨Y
if ((!xmlStrcmp(cur->name, (const xmlChar *)"product")))
{
string name;
string version;
xmlChar* szAttr = xmlGetProp(cur,BAD_CAST "name");
name=(char*)szAttr;
szAttr=xmlGetProp(cur,BAD_CAST "version");
version=(const char *)szAttr;
cout<<"Name:"<<name<<" Version:"<<version<<endl;
xmlFree(szAttr);
}
cur=cur->next;
}
xmlFreeDoc(doc);
/*return 0;*/
得出的結(jié)論是,凡是屬性值的獲取,都會(huì)調(diào)用xmlGetProp,而子元素的獲取則是通過(guò)直接訪問(wèn)內(nèi)存結(jié)構(gòu)或者類(lèi)似c++的函數(shù)訪問(wèn),不會(huì)看到函數(shù)名稱(chēng)的引用,根據(jù)這一結(jié)論和具體的調(diào)試,大致推出來(lái)licence文件的結(jié)構(gòu)如下:
代碼:
<?xml version="1.0" encoding="UTF-8"?>
<licence version="1">
<product name="aspect" version="1.0"/>
<product name="pointcut" version="1.0" />
<product name="advice" version="1.0" />
<product name="slice" version="1.0" />
<creation date="2009-8-13"/>
<type name="user">
<data code="xxxx" name="jans2002" email="jans2002@gmail.com" regnr="ccccc"/>
</type>
<signature sign="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" />
</licence>
有了這個(gè)licence文件,把它放到
C:\Program Files\pure-systems\AspectC++ Add-In\etc\目錄下
一切問(wèn)題就變得簡(jiǎn)單了,順利執(zhí)行完了0x10017930,一路殺到0x10017730
代碼:
int __thiscall sub_10017730(int this, int a2)
{
int v2; // esi@1
signed int v3; // eax@4
int v4; // ST14_4@6
int v5; // eax@20
int v7; // eax@4
int r; // [sp+4Ch] [bp+0h]@1
int v9; // [sp+3Ch] [bp-10h]@1
signed int v10; // [sp+48h] [bp-4h]@3
char v11; // [sp+20h] [bp-2Ch]@4
char v12; // [sp+4h] [bp-48h]@4
int v13; // [sp+8h] [bp-44h]@20
unsigned int v14; // [sp+1Ch] [bp-30h]@20
int v15; // [sp+18h] [bp-34h]@22
v2 = this;
v9 = r ^ dword_100242D0;
std__basic_string_char_std__char_traits_char__std__allocator_char____operator_(a2, "Invalid licence file found.");
if ( *(_BYTE *)(v2 + 5) && !*(_BYTE *)(v2 + 4) )
{
sub_10017B20();
v10 = 0;
if ( !(unsigned __int8)sub_1001A050() )
{
LABEL_23:
v10 = -1;
sub_1001A060();
return sub_1001A7B0();
}
v7 = std__operator_(&v11, v2 + 12, v2 + 40);
LOBYTE(v10) = 1;
std__operator_(&v12, v7, v2 + 68);
LOBYTE(v10) = 3;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v11);
v3 = *(_DWORD *)(v2 + 8);
if ( v3 || !*(_DWORD *)(v2 + 96) )
{
if ( v3 == 1 && *(_DWORD *)(v2 + 96) && *(_DWORD *)(v2 + 100) && *(_DWORD *)(v2 + 104) && *(_DWORD *)(v2 + 108) )
{
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, "evaluation");
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 96));
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 100));
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 104));
v4 = *(_DWORD *)(v2 + 108);
}
else
{
if ( v3 != 2
|| !*(_DWORD *)(v2 + 96)
|| !*(_DWORD *)(v2 + 100)
|| !*(_DWORD *)(v2 + 104)
|| !*(_DWORD *)(v2 + 108) )
goto LABEL_20;
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, "user");
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 96));
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 100));
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 104));
v4 = *(_DWORD *)(v2 + 108);
}
}
else
{
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, "beta");
v4 = *(_DWORD *)(v2 + 96);
}
std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, v4);
LABEL_20:
v5 = v13;
if ( v14 < 0x10 )
v5 = (int)&v13;
*(_BYTE *)(v2 + 4) = sub_10019E30(v2 + 112, v5, v15, (int)&a2);
LOBYTE(v10) = 0;
std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v12);
goto LABEL_23;
}
return sub_1001A7B0();
}
由于有了正確格式的licence,前面執(zhí)行的都很順利,一直到了sub_10019E30,跟進(jìn)去一看,一切了然了:
代碼:
bool __thiscall sub_10019E30(int this, int a2, int a3, int a4)
{
int v5; // esi@1
int v6; // eax@1
int v7; // eax@1
char v8; // [sp+4h] [bp-10h]@1
v5 = this;
v6 = EVP_sha1();
EVP_DigestInit(&v8, v6);
EVP_DigestUpdate(&v8, a2, a3);
v7 = sub_1001A030();
return EVP_VerifyFinal(&v8, v5, *(_DWORD *)(v5 + 4096), v7) == 1;
}
前面一定都是加密驗(yàn)證的,但是函數(shù)最后來(lái)了一句:
代碼:
EVP_VerifyFinal(&v8, v5, *(_DWORD *)(v5 + 4096), v7) == 1;
嘿嘿,看名字估計(jì)就是這個(gè)了,看看這個(gè)函數(shù)的返回值,1表示成功,其他表示失敗,那就是只要讓此函數(shù)永遠(yuǎn)返回1,就大功告成了,該到匯編代碼了:
代碼:
004066F0 /$ 83EC 10 sub esp, 10 ; 檢查數(shù)字簽名部分
004066F3 |. 56 push esi
004066F4 |. 8BF1 mov esi, ecx
004066F6 |. E8 81270000 call <jmp.&LIBEAY32.#333>
004066FB |. 50 push eax
004066FC |. 8D4424 08 lea eax, dword ptr [esp+8]
00406700 |. 50 push eax
00406701 |. E8 70270000 call <jmp.&LIBEAY32.#268>
00406706 |. 8B4C24 24 mov ecx, dword ptr [esp+24]
0040670A |. 8B5424 20 mov edx, dword ptr [esp+20]
0040670E |. 51 push ecx
0040670F |. 52 push edx
00406710 |. 8D4424 14 lea eax, dword ptr [esp+14]
00406714 |. 50 push eax
00406715 |. E8 56270000 call <jmp.&LIBEAY32.#269>
0040671A |. 8B4C24 34 mov ecx, dword ptr [esp+34]
0040671E |. 83C4 14 add esp, 14
00406721 |. E8 2A100000 call 00407750
00406726 |. 8B8E 00100000 mov ecx, dword ptr [esi+1000]
0040672C |. 50 push eax
0040672D |. 51 push ecx
0040672E |. 8D5424 0C lea edx, dword ptr [esp+C]
00406732 |. 56 push esi
00406733 |. 52 push edx
00406734 |. E8 49270000 call <jmp.&LIBEAY32.#290>
00406739 |. 83C4 10 add esp, 10
0040673C |. 48 dec eax
0040673D |. F7D8 neg eax
0040673F 1BC0 sbb eax, eax
00406741 90 inc eax
00406742 5E pop esi
00406743 83C4 10 add esp, 10
00406746 \. C2 0C00 retn 0C
一般來(lái)講,函數(shù)返回值都會(huì)用EAX,不管三七二十一了,先吧EAX做了再說(shuō),把上面那個(gè)黑體的
inc eax 改成nop(呵呵,nop是大家的最?lèi)?ài),機(jī)器碼是90了,這是改過(guò)的了)
保存到文件。
大功告成哈!!
身為菜鳥(niǎo),能取得這樣的結(jié)果,真是讓人興奮,謝謝各位閱讀,還請(qǐng)各位高手不吝賜教。
下載安裝程序及破解