1.[GXYCTF2019]luck_guy
elf文件,64位,目测是输入什么lucky number
不管他,直接ida f5大法
主要的函数就是getflag这个函数
设置了随机数,然后switch,本地测试基本不可能走1-5分支
目测一下,比较合理的流程就是451
4为f2赋值
5改f2的值
1拼接f1和f2
其中f1在data段,有字符串数据,f2在bss未初始化全局变量段
然后就走这个流程,一开始脑子抽了,指针那个地方读错了然后就怎么也找不到
结合汇编来读,局部变量s其实不是一个long long类型的数据而是一个字符数组
然后本地写个脚本一运行就出来了
附上本地调试的py脚本
flag = "7F666F6067756369" |
最后得到flag,但是是GXY前缀,换上ctf前缀交上才对flag{{do_not_hate_me}
2.[BJDCTF2020]JustRE
签到题
感觉像个win32的小程序
搜字符串大法
发现格式化字符串
交上就对了555
3.[FlareOn4]login
下载下来发现是html文件document.getElementById("prompt").onclick = function () {
var flag = document.getElementById("flag").value;
var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});
if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) {
alert("Correct flag!");
} else {
alert("Incorrect flag, rot again");
}
}
发现一段js代码
分析发现核心逻辑主要是这一句,只要是字母就被正则匹配到,然后执行下面这个String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});
大概就是判断字符是否小于Z,如果是第一个括号的值就变成Z否则变成z(注意此时c的值没有发生改变),然后第二个小括号是将c本身+13(注意此时c的值已经发生了改变)
再判断两个值的大小关系,如果前者大就不改变,如果后者大就-26(即相当于+13后-26,本质是原本的字符-13)
字母一共26个,如果本身变成z后大于本身+13,那么字母一定会小于n
有了这个逻辑写解密脚本就可以了,遍历加密后的字符串,如果当前字符属于a-m,那么+13,如果属于n-z,那么-13即可flag = "PyvragFvqrYbtvafNerRnfl@syner-ba.pbz"
flag = list(flag)
flaglist = ""
for i in range(len(flag)):
if (flag[i] <= 'Z' and flag[i] >= 'A') or (flag[i] >= 'a' and flag[i] <= 'z'):
if (flag[i] <= 'M' and flag[i] >= 'A') or (flag[i] <= 'm' and flag[i] >= 'a'):
flag[i] = chr(ord(flag[i]) + 13)
else:
flag[i] = chr(ord(flag[i]) - 13)
print("".join(flag))
flag{ClientSideLoginsAreEasy@flare-on.com}
看了别的师傅的wp才发现这是一种加密为ROT13加密,学到了
套用ROT13到一段文字上仅仅只需要检查字元字母顺序并取代它在13位之后的对应字母,有需要超过时则重新绕回26英文字母开 头即可。A换成N、B换成O、依此类推到M换成Z,然后序列反转:N换成A、O换成B、最后Z换成M。只有这些出现在英文字母里头的字元受影响;数字、符 号、空白字元以及所有其他字元都不变。因为只有在英文字母表里头只有26个,并且26=2×13,ROT13函数是它自己的逆反: [1]
对任何字元x:ROT13(ROT13(x))=ROT26(x)=x。
直接找个在线解密工具梭出来也可以
4.[GUET-CTF2019]re
是个ELF文件,先checksec一下
发现存在UPX壳
直接用工具脱壳./upx -d ./re
然后进入ida分析,核心逻辑很简单,求出每一位flag然后转换成字符就可以,但是有坑点
一开始是想逐步求解的,但是发现这也太反人类了,直接用正则提取吧
脚本如下
import re |
后来由于这俩坑点就怎么交也不对,搜了师傅们的wp才发现…
还有一种解法就是用z3约束器来解(学到了学到了
https://arabelatso.github.io/2018/06/14/Z3%20API%20in%20Python/
用这种方法来解也比较方便,先解出来然后再转ascii码from z3 import *
flag = [0] * 32
for i in range(len(flag)):
flag[i] = Int("flag[" + str(i) + "]")
s = Solver()
s.add(1629056 * flag[0] == 166163712)
s.add(6771600 * flag[1] == 731332800)
s.add(3682944 * flag[2] == 357245568)
s.add(10431000 * flag[3] == 1074393000)
s.add(3977328 * flag[4] == 489211344)
s.add(5138336 * flag[5] == 518971936)
s.add(7532250 * flag[7] == 406741500)
s.add(5551632 * flag[8] == 294236496)
s.add(3409728 * flag[9] == 177305856)
s.add(13013670 * flag[10] == 650683500)
s.add(6088797 * flag[11] == 298351053)
s.add(7884663 * flag[12] == 386348487)
s.add(8944053 * flag[13] == 438258597)
s.add(5198490 * flag[14] == 249527520)
s.add(4544518 * flag[15] == 445362764)
s.add(3645600 * flag[17] == 174988800)
s.add(10115280 * flag[16] == 981182160)
s.add(9667504 * flag[18] == 493042704)
s.add(5364450 * flag[19] == 257493600)
s.add(13464540 * flag[20] == 767478780)
s.add(5488432 * flag[21] == 312840624)
s.add(14479500 * flag[22] == 1404511500)
s.add(6451830 * flag[23] == 316139670)
s.add(6252576 * flag[24] == 619005024)
s.add(7763364 * flag[25] == 372641472)
s.add(7327320 * flag[26] == 373693320)
s.add(8741520 * flag[27] == 498266640)
s.add(8871876 * flag[28] == 452465676)
s.add(4086720 * flag[29] == 208422720)
s.add(9374400 * flag[30] == 515592000)
s.add(5759124 * flag[31] == 719890500)
print(s.check())
print(s.model())
5.[WUSTCTF2020]level1
源码和逻辑都很简单,对flag进行加密,然后还给了output文件,应该就是flag加密后的输出结果
写个解密脚本就行了(1,3,5,7…与1相与为1)
flagReverse = [ |
6.Youngter-drive
先去个壳
main函数中启动了两个子线程
第一个线程对于我们输入的flag进行替换
// positive sp value has been detected, the output may be wrong! |
第二个线程只是减去data段的一个计数器,并没有对我们输入的字符串进行操作,所以坑点1就是在我们输入的字符串中,只有偶数位(0,1,3,…29)被进行替换了
替换逻辑比较简单,见上面贴的注释
坑点2就是最后check的时候只检查了29位,最后一位搜的wp是填E(好像在安恒赛的时候填啥都对,然后看了一个师傅的wp觉得应该填Z,因为映射回来正好是NULL
脚本如下:key = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
flagRe = "TOiZiZtOrYaToUwPnToBsOaOapsySa"
"""
v3 = *(_BYTE *)(target_in_data_1d + source);
if ( (v3 < 97 || v3 > 122) && (v3 < 65 || v3 > 90) )
exit(0);
if ( v3 < 'a' || v3 > 'z' )
{
result = off_418000[0];
*(_BYTE *)(target_in_data_1d + source) = off_418000[0][*(char *)(target_in_data_1d + source) - '&'];
}
else
{
result = off_418000[0];
*(_BYTE *)(target_in_data_1d + source) = off_418000[0][*(char *)(target_in_data_1d + source) - '`'];
}
"""
flag = []
i = 0x1d
while i > -1:
if key.find(flagRe[i]):
position = key.find(flagRe[i])
if position <= 26:
flag.append(chr(position + 96))
else:
flag.append(chr(position + 38))
i -= 1
flag.append(flagRe[i])
i -= 1
flag = reversed(flag)
print("".join(flag))
print(len(flag))
大师傅的wp,详细解释了这个程序中反调试的部分,值得阅读:https://hx1997.github.io/2018/07/22/anheng-july-re-youngter-drive/