寫在前面:首先感謝出題人和運維的辛苦付出,讓jkd有了第一屆CTF,祝比賽越辦越好
第一次寫wp,同時由于自己太菜,賽中很多是參考了類似題的wp才能做出來,大部分直接手撕,為了讓這篇wp顯得不那么拉跨,于是參考了某究極卷投訓爺爺的腳本和出題人原汁原味的兩道wp,
1.

下載附件,點開一看

丟進exeinfope,是個64位的

打開ida64,shift+f12,搜索字串

2.

應該是非預期解(我大概也沒有哪個題是預期解
做題參考博文:
https://blog.csdn.net/xiangshangbashaonian/article/details/83476084?utm_source=app
(此處感謝安卓出題人,同樣也是這道題的出題人,讓孩子去你的博客找base64解法,沒找到,卻找到了這題的解法)
以下是反編譯的代碼

關鍵代碼是第23行,需要將陣列md5s的四組十進制數轉回十六進制,再每組進行md5解密,最后拼在一起,就是flag
然后對著博文里的抄轉十六進制的代碼

第三組少了一位,應該是轉十六進制的時候出了問題,賽后看了黃爺爺的wp后才知道最前面少了一個0,分組去在線md5網站解密
網站:https://pmd5.com/
或者使用前面所提及的博文中的腳本進行爆破
#937b8b318c5691f3 = JUST{
#b9ed7cb8a2f0bafe = you_a
#0e29cc9171a49daf = re_ri
#a99e9ee21f22d4d7 = ght_}
#flag=JUST{you_are_right_}
3.

題目提示使用uncompyle6的庫進行反編譯,沒管(直接去了在線反編譯網站
然鵝md5那題不能這么干,使用網站反編譯出來的會少代碼
這里放一下安裝及使用的代碼
pip install uncompyle6 #安裝前記得安裝pip
uncompyle6 models.pyc > models.py #將models.pyc檔案反編譯為py檔案

就一個異或,a^b=c,由于異或的特性,可以知道a^c=b,b^c=a,然后寫腳本

4.

看題目就知道要脫殼
這里講一下三類脫upx殼方式
①kali直接敲命令(小部分適用)

②工具脫殼(來自黃爺爺のwp)同樣是小部分適用
脫殼程式:https://www.cr173.com/soft/10562.html

③手動脫殼(所有都適用)
自行谷歌百度(我還沒學會/理直氣壯
拖進exeinfo查殼(寫wp才發現提示了脫殼方法)

脫殼完再次進行查殼,確保脫干凈,脫不干凈就只能手擼了(

丟ida,搜索字串,找到核心代碼

然后寫腳本,也可以手擼,一個個異或過去(我這個菜雞就是這么干的)
腳本來自黃爺爺

5.

培訓講過同類題,憑著一丟丟印象和wp做出來了
一通胡亂分析,知道是用aswd控制上下左右,I是入口,E是出口

根據最下面兩行長一點的代碼分析可知,迷宮為20x20,然后用記事本排列
此處是ida十六進制處找到的迷宮圖

貼一下黃爺爺輸出迷宮的代碼
#coding=utf-8
migong = [0x49, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x2A, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x5F, 0x2A, 0x2A, 0x5F, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x5F, 0x5F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x45, 0x2A, 0x2A]
print(len(migong))
for i in range(0,len(migong)):
print(chr(migong[i]),end = '')
if((i+1)%20==0):
print('\n')
6.

下載附件,丟進ida,進入主函式

進入getflag函式進行分析

定位v6,往上看可知v6為我們所需要輸入的,即flag值

將v7設定為指定值,可知v7可從data_start_得到
最右邊的一個個抄下來
最終真正有用的就這兩行

求v6
寫腳本(直接爆破)

貼一下出題源代碼
#include <iostream>
#include <stdlib.h>
#include <cstring>
#include <exception>
using namespace std;
template <class T>
void getflag(T *key,int len) noexcept
{
cout<<"Have a Guess of flag ?: ";
char a[100]; memset(a, NULL, sizeof a);
int i = 0;
while(cin>>a[i] && cin.peek() != '\n')
{
i++;
if(i==100)
{
cout<<"whatDoYouWantToDo?"<<flush<<endl;
system("pause");
exit(1);
}
}
int flag[100]; memset(flag, NULL, sizeof flag);
for(int j = 0 ; j < i+1 ; j++)
{
flag[j] = (int)a[j] >> 4 ^ (int)a[j];
}
for(int k = 0 ; k < len; k++)
{
if(flag[i] != key[i] || i != len - 1)
{
cout<<"TRY AGAIN!"<< flush << endl;
system("pause");
exit(1);
}
}
cout<<"Good Job ! flag is:";
for(char k:a)
{
cout<<k;
}
cout<<flush<<endl;
system("pause");
exit(0);
}
int main()
{
int key[] = {78, 80, 86, 81, 124, 87, 99, 90, 82, 77, 81, 76, 90, 93, 75, 87, 90, 86, 65, 65, 73, 86, 90, 67, 75, 75, 64, 35, 122} ;
try{
getflag<int>(key,sizeof(key)/ sizeof(key[0]));
}catch(exception &e){
cout<<e.what()<<flush<<endl;
return 1;
}
return 0;
}
以上是虛假的wp,下面是真正的wp(來自出題人)
7, rand
這道題的靈感是在之前做題的時候發現的,需要初始化亂數發生器,srand()里面的引數一般用時間(畢竟時間不可逆)達到真正的初始化,然而,如果沒有達到初始化(或者是每次的初始化的引數是固定的,那么接下來生成的亂數是相同的)比如

這是初始化引數恒為0的情況

這個是利用時間生成一個引數,
其實這個題就是利用引數固定,會生成一個固定的陣列

代碼邏輯很簡單,可以動態除錯,也可以寫個demo

利用注解解出字符,然后逆向分析就行了(a^b=c,那么a=c^b,b=c^a,這個需要說一下吧,別啥不啥就手撕了)順便說一下,打開ida直接 shift+f12會查出一個假flag(這種題也就我這種菜逼出了)
8,壓軸題
這道題是標準的c++代碼寫的,所以對于沒見過的比較陌生
找到主函式

注意看有一個輸入flag,然后v3=function1(flag);這個是主要邏輯,進函式看看

看這里,首先一個回圈對輸入的資料按位進行了異或,
然后把flag放入function2函式進行處理
打開function2

可以看到,把flag的每一位傳入然后進行的操作,我們知道A的ascii是65,Z的ascii是90,
可以看到對大寫字母的處理是轉化成相應的小寫字母(^0x20可以進行大小寫轉化,不信可以自己試試),然后-92,小寫a的ascii為97,但是減去92之后%26,說明把字母向前移動了5位(凱撒加密)然后加上97(小寫a的ascii),其實function2的函式邏輯很明顯了,就是先大小寫轉換,然后字母向前移動5位

Function3的函式更簡單,判斷傳入的引數是否相等
結合呼叫的function1函式可以看出,回傳的就是加密的flag和s比較相同的個數

然后回傳主函式
找到function4
就是計算flag的長度,
判斷function1的回傳資料是否是flag的長度
邏輯分析完畢
總結
就是把輸入的flag按位異或他的下標+1
然后大小寫轉換,向前移動5位
然后等于s
最后貼上腳本

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/234370.html
標籤:其他
