WEB
签到
打开网页发现是一个小游戏,直接查看源代码搜索 flag
super_hacker
根据题目提示,X-Forwarded-For 处存在 smarty 模板注入漏洞
访问 url/index.php 添加 Via 头和 XFF 头进行测试,发现存在 smarty 模板注入漏洞
尝试执行 phpinfo()函数,发现存在过滤,经过测试发现过滤了 i、I 和空格
使用\x20 配合 system()函数可以绕过空格限制
尝试写入一句话木马查找 flag
使用 find / -name flag 命令查找 flag 并读取
easy_web1
打开题目链接,发现内容为 flag 在哪
f12,指向一个php
访问,发现需要本地 ip 才能访问,添加 http 头进行绕过,成功读取到 flag
easy_web2
题目代码如下
cthshow的原题,百度直接打就行了
MISC
drawing
一堆 dcm 文件,用 RadiAnt DICOM Viewer 打开导入
可以进行播放,更改模式
在 im:301 处发现纯黑页面,然后进行调整为 full dynamic
CRYPTO
base 编码
R1kzRE1RWldHRTNET04yQ0dZWkRNTUpYR00zREtNWldHTTJES1JSVEdNWlRFTktHR01ZVEdOUlZJWTNES05SUkc0WlRPT0pWSVkzREVOUlJHNFpUTU5KWElRPT09PT09
直接 base64-base32-base16 就完事了
REVERSE
longlong
根据字符串判断是go文件,使用IDAGolangHelper
然后插件出现问题,可以在插件的Utils.py中将name转为str
if type(name)==bytes: name=str(name,encoding='utf-8')
重命名之后进入main_main
f5时总是call analysis failed,把错误处改为nop即可
call runtime_morestack_noctxt
大概流程是一种虚拟机,先编译程序,再运行程序
编译流程
每一个字符形成一个dword
[:6 0 ]:7 0 <:1 0 >:0 0 -:3 0 .:4 0 +:2 0 ,:5 0
实际上直接调试获得编译后的代码就可以
执行流程
固定长度指令,第一个字为操作数,第二个字为操作码
几个重要变量:
v25:指令 v18:如果v25!=0就++,=0就-- v57:v18 v14:指令起始地址 i:指令计数器 v16:一些标志位
各个指令定义
6:jz 地址 7:jg 地址 4:输出 5:输入 3:x-- 2:x++ 1:调整v18-- 0:调整v18++
解题过程
根据这些定义可以写出反汇编器
# 导入指令 data=open('1.txt').read() cmds=[] for line in data.splitlines(): for w in line.split(' '): if w and not ':' in w: cmds.append(int(w[2:],base=16)) print(cmds) # 指令长度 assert len(cmds)==0x947 to_file='' for i,cmd in enumerate(cmds): opc=cmd&0xffff opd=cmd>>16 s='unknown' if opc==0: s='v18++' elif opc==1: s='v18--' elif opc==2: s='v16[v18]++' elif opc==3: s='v16[v18]--' elif opc==4: s='output' elif opc==5: s='input' elif opc==6: s='jz 0x%x'%(opd+1) elif opc==7: s='jg 0x%x'%(opd+1) p_s='0x%02x:\t%s'%(i,s) to_file+=p_s+'\n' print(p_s) with open('out.log','w') as f: f.write(to_file)
得到反汇编指令后,发现共2547条指令,太庞大了
通过观察可以发现,有几种精简方法
- 连续的v16[v18]++,可以简化为v16[v18]+=cnt
- 连续的v16[v18]–,v18++,v18–同上
- v16[v18]–,jg上一条指令:这个是清零指令,可以精简。连同当前指令的上一条jz。。。也可以精简
# 导入指令 data=open('1.txt').read() cmds=[] for line in data.splitlines(): for w in line.split(' '): if w and not ':' in w: cmds.append(int(w[2:],base=16)) print(cmds) # 指令长度 assert len(cmds)==0x947 to_file='' i=0 delta=0 while i<len(cmds): cmd=cmds[i] opc=cmd&0xffff opd=cmd>>16 s='unknown' delta=1 if opc==0: s='v18++' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==0: cnt+=1 else: break s='v18+=%d'%cnt delta+=cnt-1 elif opc==1: s='v18--' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==1: cnt+=1 else: break s='v18-=%d'%cnt delta+=cnt-1 elif opc==2: s='v16[v18]++' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==2: cnt+=1 else: break s='v16[v18]+=%d'%cnt delta+=cnt-1 elif opc==3: s='v16[v18]--' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==3: cnt+=1 else: break s='v16[v18]-=%d'%cnt delta+=cnt-1 elif opc==4: s='output' elif opc==5: s='input' elif opc==6: s='jz 0x%x'%(opd+1) opc1=cmds[i+1]&0xffff opd1=cmds[i+1]>>16 opc2=cmds[i+2]&0xffff opd2=cmds[i+2]>>16 if opc2==7 and opd2==i and opc1==3: delta+=3-1 s='v16[v18]=0' elif opc==7: s='jg 0x%x'%(opd+1) p_s='0x%03x:\t%s'%(i,s) to_file+=p_s+'\n' print(p_s) i+=delta with open('out.log','w') as f: f.write(to_file) i=0 v16=[0]*5 v18=0 over=0 while i<len(cmds): cmd=cmds[i] opc=cmd&0xffff opd=cmd>>16 s='unknown' delta=1 if opc==0: s='v18++' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==0: cnt+=1 else: break s='v18+=%d'%cnt delta+=cnt-1 v18+=cnt elif opc==1: s='v18--' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==1: cnt+=1 else: break s='v18-=%d'%cnt delta+=cnt-1 v18-=cnt elif opc==2: s='v16[v18]++' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==2: cnt+=1 else: break s='v16[v18]+=%d'%cnt delta+=cnt-1 v16[v18]+=cnt elif opc==3: s='v16[v18]--' cnt=0 for j in range(i,len(cmds)): opc=cmds[j]&0xffff if opc==3: cnt+=1 else: break s='v16[v18]-=%d'%cnt delta+=cnt-1 v16[v18]-=cnt elif opc==4: s='output' print(chr(v16[v18])) elif opc==5: s='input' elif opc==6: s='jz 0x%x'%(opd+1) opc1=cmds[i+1]&0xffff opd1=cmds[i+1]>>16 opc2=cmds[i+2]&0xffff opd2=cmds[i+2]>>16 if opc2==7 and opd2==i and opc1==3: delta+=3-1 s='v16[v18]=0' v16[v18]=0 else: if v16[v18]==0: i=opd elif opc==7: s='jg 0x%x'%(opd+1) if v16[v18]>0: i=opd p_s='0x%03x:\t%s'%(i,s) to_file+=p_s+'\n' # print(p_s) i+=delta print(i,v18,v16)
最后得到1317条指令
发现v18最大可以取到4,所以v16是寄存器组
根据提示brainfuck,找到个可视化执行工具
https://github.com/fatiherikli/brainfuck-visualizer
通过可视化工具可以知道该程序判断的方法,即输入一个字符后判断是否相等,按字符比较的。所以重点查看输入后的部分,搜索反汇编代码中的”input”关键字
对于每一个输入的字符,都和计算出的字符比较。以第一个字符为例进行分析
0x0e5: input ; v16[v18]=input,此时v18=2 0x0e6: v18+=1 0x0e7: v16[v18]=0 ; v16[3]=0 0x0ea: v18+=1 0x0eb: v16[v18]=0 0x0ee: v16[v18]+=6 ; v16[4]=6 0x0f4: jz 0x102 0x0f5: v18-=1 0x0f6: v16[v18]+=9 ; v16[3]=6*9 0x0ff: v18+=1 0x100: v16[v18]-=1 0x101: jg 0xf5 ; 这里循环完成乘法 ; 下面开始比较过程 0x102: v18-=1 ; 其它字符可能在这两句代码之间变化,需要注意。实际上都是a*b+c的形式 0x103: v18+=1 0x104: v18-=2 ; v18=2,即用户输入 0x106: jz 0x10c 0x107: v16[v18]-=1 0x108: v18+=1 0x109: v16[v18]-=1 0x10a: v18-=1 0x10b: jg 0x107 0x10c: v16[v18]+=1 0x10d: v18+=1 0x10e: jz 0x116 ; 这里应该判断成功,所以v16[v18]=v16[3]=0,由此推出v16[v18]=6*9=54='6' 0x10f: v18-=1 0x110: v16[v18]-=1 0x111: v18+=1 0x112: v16[v18]=0 0x115: jg 0x10f ; 这里记录标志位并初始化下一个 0x116: v18-=1 0x117: jz 0x17c 0x118: v18+=2 0x11a: v16[v18]=0 0x11d: v18+=1 0x11e: v16[v18]=0 0x121: v18-=4 0x125: jz 0x132 0x126: v18+=3 0x129: v16[v18]+=1 0x12a: v18+=1 0x12b: v16[v18]+=1 0x12c: v18-=4 0x130: v16[v18]-=1 0x131: jg 0x126 0x132: v18+=4 0x136: jz 0x142 0x137: v18-=4 0x13b: v16[v18]+=1 0x13c: v18+=4 0x140: v16[v18]-=1 0x141: jg 0x137 0x142: v16[v18]=0 0x145: v16[v18]+=1 0x146: v18+=1 0x147: v18-=2 0x149: v18+=1 0x14a: jz 0x150 0x14b: v18-=1 0x14c: v16[v18]+=1 0x14d: v18+=1 0x14e: v16[v18]-=1 0x14f: jg 0x14b 0x150: v18-=1 0x151: v18+=1 0x152: v16[v18]=0 0x155: v18-=4 0x159: v16[v18]=0 0x15c: v18+=3 0x15f: jz 0x16c 0x160: v18+=1 0x161: v16[v18]+=1 0x162: v18-=4 0x166: v16[v18]+=1 0x167: v18+=3 0x16a: v16[v18]-=1 0x16b: jg 0x160 0x16c: v18+=1 0x16d: jz 0x173 0x16e: v18-=1 0x16f: v16[v18]+=1 0x170: v18+=1 0x171: v16[v18]-=1 0x172: jg 0x16e 0x173: v18-=1 0x174: v18+=1 0x175: v18-=3 0x178: v16[v18]=0 0x17b: jg 0x118 0x17c: v16[v18]=0 0x17f: v18+=1 0x180: v18-=1
可以使用相同的方法得到另外11个字符,最终flag为
678d39028ac5
记得包裹flag
暂无评论内容