pwn
[签到]stack
题目逻辑是这样的,其实就是找一个比 0x58 大很多,低一个字节小于 0x40的数,就能溢出了
1 | char *run() |
有一个 backdoor 函数,然后我看了一下没有 rdi的gadget
1 | int __fastcall backdoor(const char *a1) |
但是在call system前,因为strdup了一次 rax寄存器是一个堆上的地址,内容和read进去的数据一模一样的,所以可以构造一个 /bin/sh\x00 …… 这样一个payload,在 mov rdi,rax的时候就会取到binsh的地址,最后syscall
1 | .text:00000000004011F0 48 8B 45 F8 mov rax, [rbp+s1] |
exp
1 | from pwn import * |
Easy_SI
格式化字符串盲打,第一次做这种题,去学习了一下
https://www.anquanke.com/post/id/196722#h2-6
思路是找到elf的基地址后,爆破所有可读的段,找到got表的位置,可以通过libc中的printf 后三位 来判断got表中哪个是printf,然后把把printf_got 写成 system_got 最后输入binsh
1 | from pwn import * |
Bug_Zapper
最终目的是要走到run那 执行mmap中的shellcode,要走到mmap那的话,输入长度最大 0x10,其实是在求 0x55 - 0x65 中哪个系统调用执行完rax是0,那就会走到run那,试了一下输入长度为11个字节,也就是系统调用号为0x50 + 0xb的系统调用执行完rax是0,会走到run那,思路是构造一个长度为11字节的 syscall read to 1919180的payload,跳到1919180那再read 一次,然后写shellcode
1 | syscall ; LINUX - sys_read |
1 | add rax, 55h ; 'U' |
1 | run: |
1 | from pwn import * |
Eeeeasy_Cpp
好耶,第一次做cpp pwn,在检查输入长度的时候用的函数是strlen,可以用\x00去绕过strlen,然后修改虚表地址劫持控制流,程序开了pie,给了一个main函数的地址,可以在read username的时候通过溢出 修改 Challenge类中 成员对象的地址 为bss(用main函数算出基地址然后加偏移算出bss)的地址,然后虚表的地址为 bss + 0x10,read password的时候写backdoor的地址,这样就伪造了一个虚表,里面是backdoor,然后在call CHallenge::get的时候就会call到backdoor
1 | from pwn import * |
overflow
在输入的时候传了一个引用,可以覆盖实现一个任意地址值写,写stack_chk_fail的got为backdoor的地址,再覆盖canary触发stack_chk_fail就能劫持控制流了
1 | std::operator>><char,std::char_traits<char>>(&std::cin); |
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
1 | unsigned __int64 __fastcall sub_4012C0(__int64 a1) |
exp
1 | from pwn import * |
misc
GeekChallege
和强网杯那个fuzz一样,爆破就好了
1 | from pwn import * |
WHO?WHO?WHO
搜索了一下是零宽隐写,用这个在线的网站就能解出来了
https://yuanfux.github.io/zero-width-web/
然后解出来是一个base64的编码,开头是openssl相关的特征,把openssl相关的所有decode都试了一遍,最后在rabbit decode那成功解出来了 key是shumu
1 | U2FsdGVkX19uvldJ6CGUNff3B28QEdIjZqgUh98K+/0J16ELU8WVQydohw4P5+2M |
搜了一下这个叫dna编码,密文和明文是一个映射关系
1 | GTAGAGCTAGTCCTT{GGGTCACGGTTC_GGGTCACGGTTC_GAACGGTTC_GTAGTG_GCTTCA_GTAGACGTGGCGGTG_GTAGACTCA_TATGACCGG_GCTCGGGCT} |
https://github.com/omemishra/DNA-Genetic-Python-Scripts-CTF
用这里的脚本改一下就能解出来了
1 | mapping = { |
blockchain
CheckinNewYear
这个RPC节点是操作私有链的入口,然后水龙头是一个获取货币的接口,要在谷歌浏览器装个metaMask的虚拟钱包插件,通过设置metaMask的网络使用rpc节点访问私有链,来和题目交互
https://ctf-wiki.org/blockchain/introduction/
ctfwiki这里有一些区块链相关的名词解释,区块链其实类似于一个分布式的数据库,然后智能合约是部署在链上的程序,如果更新链的状态(添加数据 往链上部署智能合约 调用智能合约程序)就会产生一笔交易,这个交易是要收取费用的,所以要通过水龙头获取足够多的货币再和题目进行交互。要开启挑战的话,首先要往一个指定的账户发货币,然后他会给一个地址,这个地址上有题目相关的程序,可以用Remix ide编译题目的代码,然后再 at address中填入题目给的合约地址,这样就能交互了
1 | 题目源码请通过nc获取 |
1 | Can you make the isSolved() function return true? |
题目的代码是这样的,要设置 NewYear为Happy 然后再调用 isSolved,这样再菜单中选择choice 3就能得到flag了,然后只有通过require(uint160(msg.sender) |
216 * 33 * 5 * 7 * 13 * 17 * 19 * 37 * 73 * 97 * 109 * 241 * 257 * 433 * 577 * 673 * 38737 * 487824887233 ==
2**2 * 17 * 67 * 733 * 316139 * 18992431891 * 72887484710091183279372959
,”Not this Year”); 这个cmp才能设置,这个cmp其实是在判断 发起交易的人账户地址 低位是不是 0x2024,如果不是那就走不到下边
1 | // SPDX-License-Identifier: shu shao de xiao mi di |
后面发现有这样一个网站,是可以生成一个自定义低位或者高位的账户,通过这个网站生成一个低位是0x2024的账户,就能过这个cmp了
re
battle-city
直接打通关的