錦州市廣廈電腦維修|上門(mén)維修電腦|上門(mén)做系統(tǒng)|0416-3905144熱誠(chéng)服務(wù),錦州廣廈維修電腦,公司IT外包服務(wù)
topFlag1 設(shè)為首頁(yè)
topFlag3 收藏本站
 
maojin003 首 頁(yè) 公司介紹 服務(wù)項(xiàng)目 服務(wù)報(bào)價(jià) 維修流程 IT外包服務(wù) 服務(wù)器維護(hù) 技術(shù)文章 常見(jiàn)故障
錦州市廣廈電腦維修|上門(mén)維修電腦|上門(mén)做系統(tǒng)|0416-3905144熱誠(chéng)服務(wù)技術(shù)文章
騰訊游戲安全技術(shù)競(jìng)賽 - 決賽第二題進(jìn)階版 writeup

作者: 佚名  日期:2018-06-16 11:46:16   來(lái)源: 本站整理

第一題實(shí)在過(guò)于簡(jiǎn)單,一個(gè)OpenGL的3D程序, 只要CE修改camera坐標(biāo)到右上角就能看到flag了
這里分析第二題的進(jìn)階版

第一關(guān)

x32dbg載入, 各種關(guān)鍵點(diǎn)下斷, 程序依賴了兩個(gè)dll, 入口全部下斷再說(shuō),
果然點(diǎn)擊第一關(guān)的驗(yàn)證按鈕, 斷在了tmgs.dll的maln函數(shù)
其實(shí)這個(gè)程序分析的時(shí)候大量時(shí)間花在了lua函數(shù)的識(shí)別上,
1.png
function_verify核心如下:
2.png
function_verify里面是調(diào)用lua腳本進(jìn)行一個(gè)check, 這里是對(duì)照l(shuí)ua源碼一個(gè)個(gè)標(biāo)記的函數(shù)名, 花費(fèi)了很多時(shí)間
同時(shí)根據(jù)上圖可以發(fā)現(xiàn)lua腳本在luaOpcode里面,將lua的luaOpcode導(dǎo)出使用luadec反編譯可以得出驗(yàn)證邏輯,
標(biāo)準(zhǔn)版到這里基本就結(jié)束了,但是進(jìn)階版官方做了一些小動(dòng)作,lua的op_mode被做了一些處理

通過(guò)搜索關(guān)鍵詞”must be a number” 定位到luaV_execute函數(shù),此處通過(guò)和lua源代碼對(duì)比發(fā)現(xiàn)opcode做了大量改動(dòng),通過(guò)逐一對(duì)比47個(gè)lua指令switch的大量代碼,人肉得出還原表 寫(xiě)出函數(shù) de_op_codes

int de_op_codes(int en) {
    int r = 0;
    switch (en)
    {
    case 0:
        return 0xfe;
    case 6u:
    case 7u:
    case 0x16u:
    case 0x1Bu:
        return 0;
    case 0x22u:
    case 0x28u:
    case 0x29u:
    case 0x3Cu:
        return 1;
    case 0x3Eu:
        return 2;
    case 0x3Bu:
        return 3;
    case 0x12u:
        return 4;
    case 8u:
    case 0x11u:
    case 0x17u:
    case 0x36u:
        return 5;
    case 2u:
        return 6;
    case 0xDu:
        return 7;
    case 0x1Au:
        return 8;
    case 1u:
        return 9;
    case 0x1Du:
        return 0xA;
    case 0x1Fu:
        return 0xB;
    case 0xEu:
        return 0xC;
    case 0x31u:
        return 0xD;
    case 0x2Fu:
        return 0xE;
    case 0x1Eu:
        return 0xF;
    case 0x15u:
        return 0x10;
    case 0x3Au:
        return 0x11;
    case 0x13u:
        return 0x12;
    case 0x24u:
        return 0x13;
    case 0x2Bu:
        return 0x14;
    case 0x1Cu:
        return 0x15;
    case 0x2Du:
        return 0x16;
    case 0x19u:
        return 0x17;
    case 0x3Fu:
        return 0x18;
    case 0x18u:
        return 0x19;
    case 0x33u:
        return 0x1A;
    case 0xFu:
        return  0x1B;
    case 0x34u:
        return 0x1C;
    case 0x20u:
        return 0x1D;
    case 5u:
    case 9u:
    case 0xAu:
    case 0x25u:
        return 0x1E;
    case 0x30u:
        return 0x1F;
    case 0x26u:
        return 0x20;
    case 0x35u:
        return 0x21;
    case 0x38:
        return 0x22;
    case 0x2Au:
        return 0x23;
    case 0x23u:
    case 0x37u:
    case 0x39u:
    case 0x3Du:
        return 0x24;
    case 0x27u:
        return 0x25;
    case 4u:
        return 0x26;
    case 0x2Cu:
        return 0x27;
    case 0x32u:
        return 0x28;
    case 0x21u:
        return 0x29;
    case 0x03:
        return 0x2A;
    case 0xCu:
        return 0x2B;
    case 0x2Eu:
        return 0x2C;
    case 0x14u:
        return 0x2D;
    case 0xB:
        return 0x2E;
    case 0x10:
        return 46;
    default:
        return 0;
    }
}

將此函數(shù)寫(xiě)入 luadec的GET_OPCODE宏指令中,重新編譯運(yùn)行l(wèi)uadec即可還原出lua, 關(guān)鍵部分如下
3.png

可以看到程序里面通過(guò)rc4做了驗(yàn)證,由于rc4是對(duì)稱加密算法,因此只需要對(duì)dst的密文加密一次就可以得到通關(guān)密碼
4.png

第二關(guān)

通過(guò)在UE引擎關(guān)鍵地方下斷點(diǎn),發(fā)現(xiàn)第二問(wèn)處理邏輯主要在UE引擎內(nèi)部,
UE4引擎事件分發(fā)如下, 下文函數(shù)都會(huì)標(biāo)記詳細(xì)的偏移

#define RESULT_DECL = void*const Z_Param__Result

// UObject::ProcessInternal_62E860
void UObject::ProcessInternal( UObject* Context, FFrame& Stack, RESULT_DECL)
call eax

// UObject::execLet_632310
void UObject::execLet( UObject* Context, FFrame& Stack, RESULT_DECL)
call eax

// UObject::execContext_6319D0
void UObject::execContext( UObject* Context, FFrame& Stack, RESULT_DECL )
P_THIS->ProcessContextOpcode(Stack, RESULT_PARAM, /*bCanFailSilently=*/ false);

// UObject::ProcessContextOpcode_62E0B0  
void UObject::ProcessContextOpcode( FFrame& Stack, RESULT_DECL, bool bCanFailSilently )
call eax

// UObject::execFinalFunction_631D50
void UObject::execFinalFunction( UObject* Context, FFrame& Stack, RESULT_DECL )
P_THIS->CallFunction( Stack, RESULT_PARAM, (UFunction*)Stack.ReadObject() );

// UObject::CallFunction_628860
void UObject::CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function )
Function->Invoke(this, Stack, RESULT_PARAM);

// Function_Invoke_641570
void UFunction::Invoke(UObject* Obj, FFrame& Stack, RESULT_DECL)
return (*Func)(Obj, Stack, RESULT_PARAM);

一個(gè)完整流程:

-> Function_Invoke_641570 
-> UObject::ProcessInternal_62E860 
-> UObject::CallFunction_628860 
-> UObject::ProcessInternal_62E860 
-> UObject::execLet_632310
-> UObject::execContext_6319D0 
-> UObject::ProcessContextOpcode_62E0B0 
-> sub_631DF0  
-> UObject::execFinalFunction_631D50 
-> UObject::CallFunction_628860 
-> Function_Invoke_641570

核心函數(shù)在 Function_Invoke_641570 里面, 通過(guò)對(duì)此函數(shù)進(jìn)行下斷點(diǎn)可以記錄到調(diào)用了以下幾個(gè)函數(shù), 下面給出函數(shù)地址和具體功能

Function: 16D6860 check2_str_to_FString_846860
Function: 6CAF10 check2_GetUnicodeStringLength_83AF10
Function: 16D6860 check2_str_to_FString_846860
Function: 39B530 check2_md5_50B530
Function: 6CAF10 check2_GetUnicodeStringLength_83AF10
... 此處省略N個(gè)無(wú)關(guān)函數(shù)
Function: 39B340 check2_get_a_md5_50B340 
# 內(nèi)置了一個(gè)字符串, 獲取內(nèi)置字符串的md5
Function: 16D6860 check2_str_to_FString_846860
Function: 39B530 check2_md5_50B530
Function: 6C5C60 check2_main_835C60
Function: 0B420 fun_showmsg_50B420(&第二關(guān):驗(yàn)證失敗,請(qǐng)重試)
... 此處繼續(xù)省略N個(gè)無(wú)關(guān)函數(shù)

在調(diào)用顯示函數(shù)顯示出通過(guò)失敗的上一步, 就是核心判斷函數(shù)check2_main_835C60。
再次向上,是check2_md5_50B530,這一步里面會(huì)將一個(gè)字符串計(jì)算md5。
check2_md5_50B530內(nèi)部又調(diào)用check2_md5_calc_50A800進(jìn)行真正的計(jì)算。
對(duì)·check2_md5_calc_50A800·下斷點(diǎn)可以發(fā)現(xiàn)程序依次對(duì)

E0EA72E0E1C1BFFBC26E8B47AD9D809C
tencent_mobile_game+-999893888
輸入的PASSWORD

這三個(gè)內(nèi)容計(jì)算md5,
繼續(xù)單步跟蹤發(fā)現(xiàn)程序在check2_main_835C60里面對(duì) 第二次 和 第三次 字符串md5做對(duì)比, 那么key顯而易見(jiàn)了, 就是第二次的字符串
第二次的字符串tencent_mobile_game+是寫(xiě)死在程序里面的
-999893888 是這里算出來(lái)的
2_1.png
2_2.png

本題主要考察UE4事件分發(fā)流程了, 當(dāng)然如果什么都不懂的話直接IDA findcrypt在md5的地方下斷也能做出來(lái)就是了...

第三關(guān)

算法導(dǎo)出

到了這一關(guān), 點(diǎn)擊按鈕又順利斷下來(lái)了, 還是上次的dll, 進(jìn)入了ths函數(shù)
3_1.png
可以看到是在ph2.dll里面進(jìn)行的處理(基礎(chǔ)版直接是sub_100363A0,和第一關(guān)類(lèi)似的過(guò)程)
3_2.png
進(jìn)入ph2.dll,依然是lua腳本,直接dump出bin變量的腳本,
可以看到腳本是頭部有jt,是使用luajit生成的字節(jié)碼,直接使用luajit-decomp進(jìn)行反編譯, 編譯后代碼:
3_3.png

check函數(shù)內(nèi)生成了一個(gè)虛擬機(jī), 執(zhí)行虛擬機(jī)代碼對(duì)輸入的數(shù)據(jù)(plainBs)進(jìn)行加密處理, 加密后和內(nèi)置的(dstRes)進(jìn)行比對(duì)
通過(guò)對(duì)虛擬機(jī)代碼進(jìn)行導(dǎo)出,導(dǎo)出工具以及導(dǎo)出的z3t_table.lua都已經(jīng)放在附錄,
虛擬機(jī)代碼有18個(gè)指令, 分別為加減乘除判斷跳轉(zhuǎn)壓棧出棧等,且采用了大數(shù)運(yùn)算庫(kù)
這里需要對(duì)虛擬機(jī)代碼進(jìn)行分析, 附錄有我自己通過(guò)js自己重新實(shí)現(xiàn)的,
其實(shí)這里標(biāo)準(zhǔn)版和進(jìn)階版差不多了, 附錄的代碼里面附帶了標(biāo)準(zhǔn)版的實(shí)現(xiàn), 可以說(shuō)進(jìn)階版除了數(shù)大一點(diǎn)(BigNumber😄), 其余的全是一樣的

分析后如下:

算法分析

首先初始化一個(gè)b64字母表
3_4.png

然后對(duì)輸入的數(shù)據(jù)進(jìn)行分組,8個(gè)一組,前兩個(gè)做以下運(yùn)算, 生成8字節(jié)數(shù)據(jù)
3_5.png

對(duì)后6個(gè)的運(yùn)算如下

InfInt x = (x2 * 256 + x1) + (x3 * 256 * 256) + 256 * 256 * 256 * (x5 * 256 + x4 + x6 * 256 * 256);
(實(shí)際上是 x1-x6分別為二進(jìn)制8位排開(kāi))
a = savebyte + (x % 61454 * 256) 
b = (x % 54732) + ((x % 5136) % 256 * 256 * 256) 
c = (x % 25548) * 256 + ((x % 5136) >> 8) 

隨后對(duì)a/b/c/(res2)生成4個(gè)字節(jié)目標(biāo)數(shù)據(jù), 一共3*4=12字節(jié)
3_6.png

逆向思路:

dstRes分組,每組8+12=20位,前8為計(jì)算出原有前2位,后12位計(jì)算出后6位

詳細(xì)逆向過(guò)程:

前2位可以直接約束求解
3_7.png

后6位算法較為復(fù)雜, 且數(shù)據(jù)較大, 可以先化簡(jiǎn)分析
由于計(jì)算過(guò)程是

x = (x2 * 256 + x1) + (x3 * 256 * 256) + 256 * 256 * 256 * (x5 * 256 + x4 + x6 * 256 * 256)
a = savebyte + (x % 61454 * 256) 
b = (x % 54732) + ((x % 5136) % 256 * 256 * 256) 
c = (x % 25548) * 256 + ((x % 5136) >> 8) 

因此逆向過(guò)程為 abc已知, 求x(x1-x6可以通過(guò)x算出)
令R=savebyte
公式寫(xiě)為

R+(x%61454*256)=a,
(x%54732)+((x%5136)%256*256*256)=b,
(x%25548)*256+((x%5136)>>8)=c

化簡(jiǎn):

x%61454 = (a-R) >> 8
x%54732 = b & 0xFFFF
x%5136  = ((b & 0xFF0000) >> 16)  +  ((c & 0xFF) << 8)
x%25548 = c >> 8

到這一步可以看出右邊均是已知,轉(zhuǎn)化為同余方程組,
由于m不互質(zhì),因此不可以使用孫子定理, 這就和這一題一樣了
project euler problem 531

對(duì)于一個(gè)同余方程:

3_8.png

設(shè)g=gcd(n1,n2),可以得到若方程有解,則g|(a1−a2) 必成立;其逆否命題成立。

3_9.png

復(fù)雜度O(n2logn) 。因此此題中四組可以兩兩分組
x1 and x2 得到 x‘,x' and x3 得到 x'',x'' and x4 得到 answer

算出x之后,x1-x6可以這樣算出
3_10.png

至此,三道題求解完畢
3_11.png

附錄代碼

https://github.com/Tai7sy/mtp_2018_write_up

 


熱門(mén)文章
  • 機(jī)械革命S1 PRO-02 開(kāi)機(jī)不顯示 黑...
  • 聯(lián)想ThinkPad NM-C641上電掉電點(diǎn)不...
  • 三星一體激光打印機(jī)SCX-4521F維修...
  • 通過(guò)串口命令查看EMMC擦寫(xiě)次數(shù)和判...
  • IIS 8 開(kāi)啟 GZIP壓縮來(lái)減少網(wǎng)絡(luò)請(qǐng)求...
  • 索尼kd-49x7500e背光一半暗且閃爍 ...
  • 樓宇對(duì)講門(mén)禁讀卡異常維修,讀卡芯...
  • 新款海信電視機(jī)始終停留在開(kāi)機(jī)界面...
  • 常見(jiàn)打印機(jī)清零步驟
  • 安裝驅(qū)動(dòng)時(shí)提示不包含數(shù)字簽名的解...
  • 共享打印機(jī)需要密碼的解決方法
  • 圖解Windows 7系統(tǒng)快速共享打印機(jī)的...
  • 錦州廣廈電腦上門(mén)維修

    報(bào)修電話:13840665804  QQ:174984393 (聯(lián)系人:毛先生)   
    E-Mail:174984393@qq.com
    維修中心地址:錦州廣廈電腦城
    ICP備案/許可證號(hào):遼ICP備2023002984號(hào)-1
    上門(mén)服務(wù)區(qū)域: 遼寧錦州市區(qū)
    主要業(yè)務(wù): 修電腦,電腦修理,電腦維護(hù),上門(mén)維修電腦,黑屏藍(lán)屏死機(jī)故障排除,無(wú)線上網(wǎng)設(shè)置,IT服務(wù)外包,局域網(wǎng)組建,ADSL共享上網(wǎng),路由器設(shè)置,數(shù)據(jù)恢復(fù),密碼破解,光盤(pán)刻錄制作等服務(wù)

    技術(shù)支持:微軟等
    主站蜘蛛池模板: 亚洲中文字幕无码一去台湾| 精品人妻无码区在线视频 | 最新无码专区视频在线| 国产精品无码专区在线观看| 亚洲Av永久无码精品黑人| 无码成人AAAAA毛片| 2020无码专区人妻系列日韩| 黑人巨大无码中文字幕无码| 亚洲精品人成无码中文毛片| 国产精品无码AV一区二区三区| 日韩人妻无码精品一专区| 国产AV无码专区亚洲AV麻豆丫| 亚洲一级特黄无码片| 久久精品成人无码观看56| 亚洲精品无码专区久久| 无码丰满熟妇浪潮一区二区AV| 狠狠躁天天躁中文字幕无码| 亚洲av无码一区二区三区天堂古代| 亚洲AV无码国产精品色| 一本之道高清无码视频| 久久久久亚洲av无码专区导航| 热の无码热の有码热の综合| 亚洲Aⅴ无码专区在线观看q| 无码毛片一区二区三区视频免费播放| 亚洲人成无码网站| 久久国产精品成人无码网站| 无码区国产区在线播放| 亚洲精品国产日韩无码AV永久免费网| 人妻丰满av无码中文字幕| 免费看无码特级毛片| 精品高潮呻吟99av无码视频| 亚洲永久无码3D动漫一区| 亚洲高清无码专区视频| 亚洲爆乳无码专区www| 亚洲AV无码成人精品区天堂| 日韩AV无码不卡网站| 亚洲中文字幕无码av永久| 无码国产色欲XXXXX视频| 国产成人亚洲综合无码精品| 亚洲精品97久久中文字幕无码| 在线无码午夜福利高潮视频|