本發(fā)明涉及一種基于控制流復(fù)雜化的Java代碼混淆方法,屬于計(jì)算機(jī)安全領(lǐng)域。
背景技術(shù):
伴隨著移動(dòng)互聯(lián)網(wǎng)的興起,移動(dòng)端應(yīng)用越來(lái)越普及,這些應(yīng)用充分利用了移動(dòng)設(shè)備的計(jì)算能力和便攜性,方便了人們的生活,但是移動(dòng)端應(yīng)用中有大量的Java程序。Java程序在編譯后以打包的.class文件的形式分發(fā),這些.class文件都是Java字節(jié)碼,并且原始的Java字節(jié)碼可以通過反編譯的方法還原出與原代碼差別只在注釋的源代碼。這就給了攻擊者或者其他的不法分子機(jī)會(huì)。這帶來(lái)的主要問題如下:
1.軟件盜版,不法分子通過反編譯之后的源代碼可以輕易的復(fù)制出與原來(lái)的軟件功能相同或相近的軟件,或者破解出不需要激活的軟件。
2.篡改,修改軟件源代碼,不改變軟件的使用功能,但是在其中添加了廣告或者其他的惡意代碼和病毒。
為了解決這些問題,提出了代碼混淆的方法,主要分為四類:布局混淆轉(zhuǎn)換、控制混淆轉(zhuǎn)換、數(shù)據(jù)混淆轉(zhuǎn)換以及預(yù)防性混淆轉(zhuǎn)換。這些方法主要是用來(lái)應(yīng)對(duì)反編譯,對(duì)循環(huán)結(jié)構(gòu)利用不足。
技術(shù)實(shí)現(xiàn)要素:
為了解決上述技術(shù)問題,本發(fā)明提供了一種基于控制流復(fù)雜化的Java代碼混淆方法。
為了達(dá)到上述目的,本發(fā)明所采用的技術(shù)方案是:
一種基于控制流復(fù)雜化的Java代碼混淆方法,包括以下步驟,
步驟1,構(gòu)建不透明謂詞集合;
步驟2,發(fā)現(xiàn)循環(huán)結(jié)構(gòu);
步驟3,拆開循環(huán)結(jié)構(gòu);
步驟4,在拆開的循環(huán)結(jié)構(gòu)中插入不透明謂詞集合;
步驟5,復(fù)雜化循環(huán)結(jié)構(gòu)。
不透明謂詞集合包括構(gòu)造恒為真的謂詞集合T以及恒為假的謂詞集合F。
發(fā)現(xiàn)循環(huán)結(jié)構(gòu)的過程為,
S11,遍歷class文件尋找條件跳轉(zhuǎn)指令M;
S12,找到條件跳轉(zhuǎn)指令M的跳轉(zhuǎn)標(biāo)簽E;
S13,查看跳轉(zhuǎn)標(biāo)簽E所在位置的上一條指令是否為無(wú)條件跳轉(zhuǎn)指令N,如果是,找到無(wú)條件跳轉(zhuǎn)指令N的跳轉(zhuǎn)標(biāo)簽B;
S14,判斷跳轉(zhuǎn)標(biāo)簽B是否在條件跳轉(zhuǎn)指令M之前,如果是,遍歷跳轉(zhuǎn)標(biāo)簽B到條件跳轉(zhuǎn)指令M之間的代碼段,查看是否還有其余跳轉(zhuǎn)指令,如果沒有,那么從跳轉(zhuǎn)標(biāo)簽B到跳轉(zhuǎn)標(biāo)簽E之間的代碼段為一個(gè)循環(huán)結(jié)構(gòu)。
拆開循環(huán)結(jié)構(gòu)的過程為,
S21,定義從跳轉(zhuǎn)標(biāo)簽B到無(wú)條件跳轉(zhuǎn)指令N之前的代碼段為循環(huán)結(jié)構(gòu)的循環(huán)體,定義循環(huán)結(jié)構(gòu)原先具有的循環(huán)體的跳轉(zhuǎn)標(biāo)簽B記為B0,定義復(fù)制循環(huán)體的次數(shù)為k,計(jì)數(shù)器i=0;
S22,i=i+1;
S23,在無(wú)條件跳轉(zhuǎn)指令N之前插入一循環(huán)體,插入的循環(huán)體的跳轉(zhuǎn)標(biāo)簽記為Bi;
S24,判斷i是否大于等于k,如果否,則轉(zhuǎn)至步驟S22,如果是,則轉(zhuǎn)至步驟S25;
S25,去掉無(wú)條件跳轉(zhuǎn)指令N,在同樣的位置插入代碼塊D,所述代碼塊D根據(jù)輸入和局部變量的狀態(tài)跳轉(zhuǎn)B0到Bk中的任何一個(gè).
在拆開的循環(huán)結(jié)構(gòu)中插入不透明謂詞集合的過程為,
S31,定義跳轉(zhuǎn)標(biāo)簽為B0、B1、…、Bk的循環(huán)體的的條件謂詞分別為Cal_A0、Cal_A1、…、Cal_A k;
S32,定義i=0;
S33,如果i小于等于k,則轉(zhuǎn)至步驟S34,否則結(jié)束;
S34,修改Cal_Ai,從不透明謂詞集合中選擇若干謂詞,與循環(huán)體中原本的謂詞結(jié)合,結(jié)合后的謂詞真假不變;
S35,i=i+1;轉(zhuǎn)至步驟S33。
復(fù)雜化循環(huán)結(jié)構(gòu)的過程為,
S41,定義循環(huán)結(jié)構(gòu)的循環(huán)體為C0、C1、…、Ck;
S42,定義i=0;
S43,如果i小于等于k,則轉(zhuǎn)至步驟S44,否則結(jié)束;
S44,在循環(huán)體Ci中隨機(jī)地添加與不透明謂詞相關(guān)的代碼,這些代碼不改變不透明謂詞的真假;
S45,調(diào)用構(gòu)造有向無(wú)環(huán)圖的函數(shù),得到DAG結(jié)構(gòu);
DAG結(jié)構(gòu)中的每一個(gè)節(jié)點(diǎn)都是循環(huán)體Ci中的一個(gè)位置,每一條有向邊代表從起點(diǎn)所代表位置到終點(diǎn)所代表位置之間的代碼段;
S46,計(jì)算每一條有向邊在DAG中的一個(gè)拓?fù)湫騎S;
S47,將代碼段按照拓?fù)湫騎S替換掉原本的循環(huán)體Ci;
S48,尋找下一個(gè)代碼段間的間隔;
S49,如果間隔之前緊鄰的代碼段,在DAG結(jié)構(gòu)中沒有后續(xù)的代碼段執(zhí)行,轉(zhuǎn)至步驟S410,否則轉(zhuǎn)至步驟S411;
S410,插入跳轉(zhuǎn)指令直接跳轉(zhuǎn)到S47中替換掉的循環(huán)體Ci的結(jié)束位置,轉(zhuǎn)至步驟S412;
S411,插入隨即條件或者與輸入相關(guān)的條件,跳轉(zhuǎn)到在DAG結(jié)構(gòu)中緊鄰在這個(gè)代碼段之后的代碼段上;
S412,判斷是否還有代碼段間的間隔沒有插入跳轉(zhuǎn)指令,如果是,轉(zhuǎn)至步驟S48,否則轉(zhuǎn)至步驟S423;
S423,i+=1,轉(zhuǎn)至步驟S43。
本發(fā)明所達(dá)到的有益效果:本發(fā)明克服了現(xiàn)有代碼混淆方法對(duì)循環(huán)結(jié)構(gòu)利用不足的缺點(diǎn),實(shí)現(xiàn)了利用循環(huán)結(jié)構(gòu)的控制流復(fù)雜化方法。
附圖說明
圖1為本發(fā)明的流程圖。
圖2為拆開循環(huán)結(jié)構(gòu)的流程圖。
圖3為復(fù)雜化循環(huán)結(jié)構(gòu)的流程圖。
具體實(shí)施方式
下面結(jié)合附圖對(duì)本發(fā)明作進(jìn)一步描述。以下實(shí)施例僅用于更加清楚地說明本發(fā)明的技術(shù)方案,而不能以此來(lái)限制本發(fā)明的保護(hù)范圍。
如圖1所示,一種基于控制流復(fù)雜化的Java代碼混淆方法,包括以下步驟:
步驟1,構(gòu)建不透明謂詞集合。
利用Java中的引用的比較來(lái)構(gòu)造不透明謂詞集合,不透明謂詞集合包括構(gòu)造恒為真的謂詞集合T以及恒為假的謂詞集合F。
步驟2,發(fā)現(xiàn)循環(huán)結(jié)構(gòu)。
從Java代碼段中發(fā)現(xiàn)循環(huán)結(jié)構(gòu),它們應(yīng)該類似于這種情況:
代碼如下:
B:Cal_A
If not A go to E;
C
Go to B;
E:
具體過程如下:
S11,遍歷class文件尋找條件跳轉(zhuǎn)指令M;
S12,找到條件跳轉(zhuǎn)指令M的跳轉(zhuǎn)標(biāo)簽E;
S13,查看跳轉(zhuǎn)標(biāo)簽E所在位置的上一條指令是否為無(wú)條件跳轉(zhuǎn)指令N,如果是,找到無(wú)條件跳轉(zhuǎn)指令N的跳轉(zhuǎn)標(biāo)簽B;
S14,判斷跳轉(zhuǎn)標(biāo)簽B是否在條件跳轉(zhuǎn)指令M之前,如果是,遍歷跳轉(zhuǎn)標(biāo)簽B到條件跳轉(zhuǎn)指令M之間的代碼段,查看是否還有其余跳轉(zhuǎn)指令,如果沒有,那么從跳轉(zhuǎn)標(biāo)簽B到跳轉(zhuǎn)標(biāo)簽E之間的代碼段為一個(gè)循環(huán)結(jié)構(gòu)。
步驟3,拆開循環(huán)結(jié)構(gòu)。
具體過程如圖2所示,
S21,定義從跳轉(zhuǎn)標(biāo)簽B到無(wú)條件跳轉(zhuǎn)指令N之前的代碼段為循環(huán)結(jié)構(gòu)的循環(huán)體,定義循環(huán)結(jié)構(gòu)原先具有的循環(huán)體的跳轉(zhuǎn)標(biāo)簽B記為B0,定義復(fù)制循環(huán)體的次數(shù)為k,計(jì)數(shù)器i=0;
S22,i=i+1;
S23,在無(wú)條件跳轉(zhuǎn)指令N之前插入一循環(huán)體,插入的循環(huán)體的跳轉(zhuǎn)標(biāo)簽記為Bi;
S24,判斷i是否大于等于k,如果否,則轉(zhuǎn)至步驟S22,如果是,則轉(zhuǎn)至步驟S25;
S25,去掉無(wú)條件跳轉(zhuǎn)指令N,在同樣的位置插入代碼塊D,所述代碼塊D根據(jù)輸入和局部變量的狀態(tài)跳轉(zhuǎn)B0到Bk中的任何一個(gè)。
拆開后的代碼如下:
B0:Cal_A
IfnotAgotoB1:
C
B1:Cal_A
IfnotAgotoB2:
C
…
Bi:Cal_A
IfnotAgotoE:
C
D
E:
步驟4,在拆開的循環(huán)結(jié)構(gòu)中插入不透明謂詞集合。
具體過程為:
S31,定義跳轉(zhuǎn)標(biāo)簽為B0、B1、…、Bk的循環(huán)體的的條件謂詞分別為Cal_A0、Cal_A1、…、Cal_A k;
S32,定義i=0;
S33,如果i小于等于k,則轉(zhuǎn)至步驟S34,否則結(jié)束;
S34,修改Cal_Ai,從不透明謂詞集合中選擇若干謂詞,與循環(huán)體中原本的謂詞結(jié)合,結(jié)合后的謂詞真假不變;
S35,i=i+1;轉(zhuǎn)至步驟S33。
步驟5,復(fù)雜化循環(huán)結(jié)構(gòu)。
如圖3所示,具體過程為:
S41,定義循環(huán)結(jié)構(gòu)的循環(huán)體為C0、C1、…、Ck;
S42,定義i=0;
S43,如果i小于等于k,則轉(zhuǎn)至步驟S44,否則結(jié)束;
S44,在循環(huán)體Ci中隨機(jī)地添加與不透明謂詞相關(guān)的代碼,這些代碼不改變不透明謂詞的真假;
S45,調(diào)用構(gòu)造有向無(wú)環(huán)圖的函數(shù)create_DAG(empty_dag,0,empty_map),得到DAG結(jié)構(gòu);
DAG結(jié)構(gòu)中的每一個(gè)節(jié)點(diǎn)都是循環(huán)體Ci中的一個(gè)位置,每一條有向邊代表從起點(diǎn)所代表位置到終點(diǎn)所代表位置之間的代碼段;
S46,計(jì)算每一條有向邊在DAG中的一個(gè)拓?fù)湫騎S;
S47,將代碼段按照拓?fù)湫騎S替換掉原本的循環(huán)體Ci;
S48,尋找下一個(gè)代碼段間的間隔;
S49,如果間隔之前緊鄰的代碼段,在DAG結(jié)構(gòu)中沒有后續(xù)的代碼段執(zhí)行,轉(zhuǎn)至步驟S410,否則轉(zhuǎn)至步驟S411;
S410,插入跳轉(zhuǎn)指令直接跳轉(zhuǎn)到S47中替換掉的循環(huán)體Ci的結(jié)束位置,轉(zhuǎn)至步驟S412;
S411,插入隨即條件或者與輸入相關(guān)的條件,跳轉(zhuǎn)到在DAG結(jié)構(gòu)中緊鄰在這個(gè)代碼段之后的代碼段上;
S412,判斷是否還有代碼段間的間隔沒有插入跳轉(zhuǎn)指令,如果是,轉(zhuǎn)至步驟S48,否則轉(zhuǎn)至步驟S423;
S423,i+=1,轉(zhuǎn)至步驟S43。
上述方法克服了現(xiàn)有代碼混淆方法對(duì)循環(huán)結(jié)構(gòu)利用不足的缺點(diǎn),實(shí)現(xiàn)了利用循環(huán)結(jié)構(gòu)的控制流復(fù)雜化方法。
以上所述僅是本發(fā)明的優(yōu)選實(shí)施方式,應(yīng)當(dāng)指出,對(duì)于本技術(shù)領(lǐng)域的普通技術(shù)人員來(lái)說,在不脫離本發(fā)明技術(shù)原理的前提下,還可以做出若干改進(jìn)和變形,這些改進(jìn)和變形也應(yīng)視為本發(fā)明的保護(hù)范圍。