吾愛破解 - LCG - LSG |安卓破解|病毒分析|001aa.com

 找回密碼
 注冊[Register]

QQ登錄

时时彩平台只需一步,快速開始

搜索
查看: 2016|回復: 28

[CTF] 2020網鼎杯青龍組部分逆向題

  [復制鏈接]
樓主
L15263458908 發表于 2020-5-11 17:09 回帖獎勵
本帖最后由 L15263458908 于 2020-5-12 21:53 編輯

2020網鼎杯青龍組部分逆向題

signal
方法一
打開程序,可以很明顯的看到,這是一個虛擬機指令的逆向




進入關鍵函數進行分析




進行觀察,可以發現,v4 與 a1[v10 + 1]比較 是判斷條件
a1是輸入的opcode, 而v4來自v5,v5由flag進行運算得到
flag--->v5---->v4
所以我們要得到v4,然后推v5,在得到flag

我們復制IDA中的代碼,進行修改,來得到v4的值和執行順序,即上圖的V10



代碼如下
[C++] 純文本查看 復制代碼
#include "pch.h"
#include <stdio.h>
#include <string.h>

unsigned char vmcode[] =
{
  0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00,
  0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x21, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
  0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
  0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3F, 0x00,
  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
  0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x07, 0x00,
  0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x33, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00,
  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0xFF, 0xFF,
  0x07, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
  0x00, 0x00, 0xF1, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
  0x28, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x84, 0xFF,
  0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF,
  0x07, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x07, 0x00,
  0x00, 0x00, 0x7A, 0x00, 0x00, 0x00
};

int * a = (int *)vmcode;

int __cdecl vm_operad(int *opcode, int len_114)
{
        char order[114] = {};        //順序         即i
        char flag[100]; // [esp+13h] [ebp-E5h]
        char v4[100]; // [esp+77h] [ebp-81h]
        char v5; // [esp+DBh] [ebp-1Dh]
        int j; // [esp+DCh] [ebp-1Ch]
        int m; // [esp+E0h] [ebp-18h]
        int k; // [esp+E4h] [ebp-14h]
        int n; // [esp+E8h] [ebp-10h]
        int i; // [esp+ECh] [ebp-Ch]
        int s = 0;

        i = 0;
        n = 0;
        k = 0;
        m = 0;
        j = 0;
        while (1)
        {
                if (i >= len_114)                         // 成功的地方
                        break;
                switch (opcode[i])
                {
                case 1:
                        v4[m] = v5;
                        ++i;
                        ++m;
                        ++n;
                        break;
                case 2:
                        v5 = opcode[i + 1] + flag[n];
                        i += 2;
                        break;
                case 3:
                        v5 = flag[n] - opcode[i + 1];
                        i += 2;
                        break;
                case 4:
                        v5 = opcode[i + 1] ^ flag[n];
                        i += 2;
                        break;
                case 5:
                        v5 = opcode[i + 1] * flag[n];
                        i += 2;
                        break;
                case 6:
                        ++i;
                        break;
                case 7:
                        v4[k] = opcode[i + 1];                        // 打印關鍵數據V4
                        printf("%#X, ", v4[k]);                
                        ++k;
                        i += 2;
                        break;
                case 8:
                        flag[j] = v5;
                        ++i;
                        ++j;
                        break;
                case 10:
                        scanf("%s", flag);                                // 輸入flag                //長度是15
                        ++i;
                        break;
                case 11:
                        v5 = flag[n] - 1;
                        ++i;
                        break;
                case 12:
                        v5 = flag[n] + 1;
                        ++i;
                        break;
                }
                order[s++] = i;
        }
        printf("執行順序是: ");
        for (int ss = 0; ss < strlen(order); ss++) {
                printf("%d, ", order[ss]);
        }

        return 0;
}

int main()
{        
        vm_operad(a, 114);
        
        return 0;
}


得到結果


v4 = { 0X22, 0X3F, 0X34, 0X32, 0X72, 0X33, 0X18, 0XFFFFFFA7, 0X31, 0XFFFFFFF1, 0X28, 0XFFFFFF84, 0XFFFFFFC1, 0X1E, 0X7A };
order[100] = { 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114 };
再寫解密函數逆推flag
[C++] 純文本查看 復制代碼
int decode(int * opcode, int len_114)
{
        int i;
        //獲取flag 的關鍵數據
        unsigned char v4[] = { 0X22, 0X3F, 0X34, 0X32, 0X72, 0X33, 0X18, 0XFFFFFFA7, 0X31, 0XFFFFFFF1, 0X28, 0XFFFFFF84, 0XFFFFFFC1, 0X1E, 0X7A };
        //執行opcode 的索引,即執行順序
        char order[100] = { 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114 };
        unsigned char flag[100] = {};
        int m = 15;
        int n = 15;
        int j = 15;
        int v5;
        for (int k = strlen(order) - 1; k >= 0 ; k--)
        {
                i = order[k];
                switch (opcode[i])                                // 倒序執行
                {
                case 1:
                        --m;
                        --n;
                        v5 = v4[m];
                        break;
                case 2:
                        flag[n] = v5 - char(opcode[i + 1]) ;
                        break;
                case 3:
                    flag[n] = v5 + char(opcode[i + 1]);
                        break;
                case 4:
                        flag[n] = (v5 ^ opcode[i + 1]) & 0XFF;
                        break;
                case 5:
                        flag[n] = v5 / opcode[i + 1];
                        break;
                case 6:
                        break;
                case 8:
                        v5 = flag[--j];
                        break;
                case 11:
                        flag[n] = v5 + 1;
                        break;
                case 12:
                        flag[n] = v5 - 1;
                        break;
                }
        }

        printf("%s", flag);
        return 0;
}


得到flag是 757515121f3d478
方法二:
通過Ponce插件符號執行來一步步獲取flag




關于Ponce插件下介紹及下載->
方法三: 使用python angr符號執行解決
代碼如下
[Python] 純文本查看 復制代碼
import angr
p = angr.Project('signal.exe')
st = p.factory.entry_state()
sm = p.factory.simulation_manager(st)
sm.explore(find=0x40175E, avoid=0x4016E6)
print(sm.found[0].posix.dumps(0))




jocker
打開程序,找到main函數,F5發現無法反編譯





手動修復下棧指針




問題出現在401838那里



對401833那個位置按ALT+ K



修改棧偏移



F5看偽代碼


wrong是對flag進行了一個簡單的加密
omg對加密的flag進行判斷,得到flag為flag{fak3_alw35_sp_me!!} 提交發現錯誤
然后調試起來,進入下面的encrypt函數



一個簡單的異或判斷
寫腳本打印出flag的前一半
[Python] 純文本查看 復制代碼
a = [0XE, 0XD, 9, 6, 0X13, 5, 0X58, 0X56, 0X3E, 6, 0XC, 0X3C, 0X1F, 0X57, 0X14, 0X6B, 0X57, 0X59, 0XD]
b = "hahahaha_do_you_find_me?"
c = [chr((a[i] ^ ord(b[i]))& 0xff) for i in range(len(a))]
print "".join(c)

結果為:
flag{d07abccf8a410c

最后進入finally函數

根據提示說 我隱藏了后一半部分,,前面
flag{d07abccf8a410c是19個字符,而flag是24個字符,還差5個,最后一個肯定是 “}”
于是將v7 與 } 異或得到 71
寫個腳本,將37,116,112,38,58 全部異或71
[Python] 純文本查看 復制代碼
a = [37,116,112,38,58]
flag = "".join([chr(i ^ 71) for i in a])
print flag


得到flag的后半部分
b37a}
拼接,即為flag--->flag{d07abccf8a410cb37a}

------------------------------
題目鏈接:
鏈接:
提取碼:gemn

免費評分

參與人數 13吾愛幣 +13 熱心值 +13 收起 理由
deoplljj + 1 + 1 謝謝@Thanks!
Ginobili + 1 + 1 謝謝@Thanks!
SinnerDusk + 1 + 1 用心討論,共獲提升!
soyiC + 1 + 1 用心討論,共獲提升!
鎮北看雪 + 1 + 1 我很贊同!
smile5 + 1 熱心回復!
FinchK + 1 + 1 歡迎分析討論交流,吾愛破解論壇有你更精彩!
笙若 + 1 + 1 感謝發布原創作品,吾愛破解論壇因你更精彩!
Hotspur + 1 + 1 我很贊同!
Oohuo + 1 + 1 用心討論,共獲提升!
2008yxp + 1 + 1 用心討論,共獲提升!
Ps出來的小趙 + 3 + 1 趕在黑米之前加分再說
fishinwhater + 1 雖然我看不太懂,但確實大佬牛逼

查看全部評分

發帖前要善用論壇搜索功能,那里可能會有你要找的答案或者已經有人發布過相同內容了,請勿重復發帖。

推薦
q2510908331 發表于 2020-5-12 11:01
xmhwws 發表于 2020-5-11 18:55
大佬,這個是怎么操作的?還是通過插件實現的?

請詳細說說

Shife + E  Expore Data  IDA 自帶的. 可以 Edit選項中看到.
推薦
 樓主| L15263458908 發表于 2020-5-11 18:59 |樓主
xmhwws 發表于 2020-5-11 18:55
大佬,這個是怎么操作的?還是通過插件實現的?

請詳細說說

變成數組類型之后 shift +e

免費評分

參與人數 1吾愛幣 +1 熱心值 +1 收起 理由
xmhwws + 1 + 1 謝謝@Thanks!

查看全部評分

沙發
赤座燈里 發表于 2020-5-11 17:51
3#
xmhwws 發表于 2020-5-11 18:55
大佬,這個是怎么操作的?還是通過插件實現的?

請詳細說說
5#
FinchK 發表于 2020-5-11 19:09
厲害了,學到了。
6#
victoryang00 發表于 2020-5-11 19:40
大佬牛逼,這joker是個雙線程的,我同伴弄了個假的flag
7#
 樓主| L15263458908 發表于 2020-5-11 19:48 |樓主
victoryang00 發表于 2020-5-11 19:40
大佬牛逼,這joker是個雙線程的,我同伴弄了個假的flag

這題最難的是flag后5位,,,,,腦洞題,
8#
wh1sper 發表于 2020-5-11 21:10
本帖最后由 wh1sper 于 2020-5-11 21:13 編輯

這次逆向好像很難,不過最后半小時就看別人垂直上分
9#
新手12138 發表于 2020-5-11 22:02
L15263458908 發表于 2020-5-11 19:48
這題最難的是flag后5位,,,,,腦洞題,

腦洞題我就很難受
10#
 樓主| L15263458908 發表于 2020-5-11 22:10 |樓主
wh1sper 發表于 2020-5-11 21:10
這次逆向好像很難,不過最后半小時就看別人垂直上分

逆向除了第二道都很簡單,,,,難的是雜項,,那個漢信碼我拼了得1個多小時,硬是沒掃出來,,,
您需要登錄后才可以回帖 登錄 | 注冊[Register]

本版積分規則 警告:本版塊禁止灌水或回復與主題無關內容,違者重罰!

快速回復 收藏帖子 返回列表 搜索

RSS訂閱|小黑屋|聯系我們|吾愛破解 - LCG - LSG ( )

GMT+8, 2020-5-25 12:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回復 返回頂部 返回列表
时时彩平台官网-欢迎您 时时彩平台注册-爱问知识人 时时彩平台app-互动百科 时时彩平台投注-百科词条 超级快三-搜霸天下 时时彩平台邀请码-即可搜索 时时彩平台开户-新浪爱彩 彩神大发快三-一定牛 彩神大发快三官网-360云盘 彩神大发快三注册-百度耨米