re1
下载下来是一个exe
文件,先运行下
随便输入当然不对,于是用ida
打开,但是没有发现main
函数,那么flag
应该这里就不是用算法生成的,直接丢到linux
下使用strings
命令查看flag的相关字段
game
依次输入1,2,3,4,5,6,7,8 就能获得flag
当然这样是不能满足我们学习欲望的,打开ida
,还是没有main
函数,按shift+f12
查看.rdata
段的信息,flag如果显示应该是有提示的,所以留意下有flag字样的地方
双击进去,看旁边有个sub_45E940
的函数,点进去F5
反C代码
看它每个变量地址都是差1排的,然后再到最低比的for循环处,*(&v3 + i)
,这里比如说(&v3 + 1)
就是v4
,同理后面的*(&v60 + i)
也是这么计算的,总共生成56个字符
算法逻辑很清晰,使用v3~v59
和 v60 ~ v116
进行异或操作,之后的结果在和0x13
进行一次异或操作,写出python脚本
v3=[18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0]
v60=[123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0]
flag = ''
for i in range(0, 56):
tmp = v3[i] ^ v60[i]
flag += chr(tmp ^ 0x13)
print flag
Hello, CTF
下载下来是个exe文件,运行一下大概也是输入flag才能返回true之类的
用ida32位
打开(对于exe文件如果ida64位F5不了,就换32位的),这次有main函数
那么v10是我们输入,v13的值就是上面的的a437261636b4d65
,点进去可以看到它的值
好了,问题是v13是我们输入的,只能有17位,而这里的v10有34位,34位刚好是17位的倍数,16进制转字符,刚好位数相同因此hex解码一下,获得flag
open-source
下载下来是一个c文件,直接给了源码,看逻辑是要输入3个参数,都满足4个if判断后会根据输入的3个参数进行计算获得flag
这里第一个填0xcafe
转10进制的51966
,第二个是要满足除17余8,并且除5不能余3, 因为计算量不大,枚举几个就能算出值为25
,第三个值就是h4cky0u
编译下code.c文件
gcc code.c -o code
然后运行,答案为c0ffee
simple-unpack
这道题下载下来是个二进制文件,看到题目提示是有个壳的,而题目估计就是upx
壳了,当然可以winhex
看看,也能看到
kali下能够直接脱upx
upx -d simple2
然后直接用strings
搜flag
字符串即可
insanity
下载下来是个二进制文件,放到linux中先用file看看是多少位,然后用对应位数的ida打开文件
直接用shift +F12
看到存储数据的段中就有flag
logmein
二进制文件先看文件信息
运行下,是要猜flag
那么用ida打开分析流程
问题在于v7和v8进行异或运算处, v8的值已经知道了,而v7的值要转换成字符串,在28537194573619560LL
上按R键就能转换
但是这里就有大端序和小端序的概念,因为绝大部分电脑都是小端序所有要把这个字符串反转,所以最后的python脚本如下
a = ':\"AL_RT^L*.?+6/46'
b = 'ebmarah'[::-1]
ans = ""
print len(a)
print a
print len(b)
print b
for i in range(0,len(a)):
print a[i] + " " + b[i % 7]
ans += chr(ord(a[i]) ^ ord(b[i % 7]))
print ans
no-strings-attached
依旧是二进制文件,先用file查看,再丢入ida
进入main函数后,前面3个估计就是输出前面2行的代码,不用管它,点开authenticate()
函数
有个decrypt()
函数,看名字对s进行了解密,继续跟进也看不懂是啥,估计flag在程序运行中会出现,但是因为种种原因,最后不会输出到界面,于是在linux下使用gdb动态调试,从中找到flag值
正常调一遍的时候进入到authenticate()
就会开始解密,汇编过程太复杂我看不懂,所以我把断点下在decryp()
执行后的地方,看地址可以用ida
看到
下断点
跑起来后,查看$eax寄存器所指的的地址的内容即可,至于为什么看eax寄出去,看了别人的writeup都没有说清楚,我估计看上面的汇编代码,之后把eax寄存器放到[ebp+s2]地址里面去了,所以解密值可能在$eax寄存器所指的地址中
x/10sw $eax
x/:查看内存的命令
10:显示10行
s:用字符串形式表示
w:4个字节为一个单位
python-trade
用python编写的程序生成了pyc文件,安装反py的插件即可
pip install uncompyle
uncompyle6 Py.pyc
当然可用重定向下输出的内容到 文件中
看看代码逻辑无非就是把flag异或然后base64编码,于是按照逻辑写个解码的流程
import base64
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
tmp = base64.b64decode(correct)
result = ''
for i in tmp:
x = ord(i) - 16
x = x ^ 32
result += chr(x)
print result
运行即可获取flag
csaw2013reversing2
下载下来是个exe文件,题目提示运行就有flag,但是运行是乱码,于是用ida看看流程
在if之后MessageBoxA
就开始输出flag的信息了,而flag估计是lpMen
的值,那么应该是在if处进行了编码操作
仔细看这段汇编代码,在ds:IsDebuggerPresent
处判断是否使用调试器,如果不是会跳到loc_4010B9
,但是如果是调试器会在int 3
处被中断,上面的call_sub40102A
后进行的跳转判断也无法满足,但是我们要通过判断所以必须要使一个条件满足
根据汇编代码的从下至下运行,也就不改什么判断语句了,直接把 jz short loc_4010B9
改成nop
,就不会跳到loc_4010B9
了,但是之后会运行__debugkreak()
,也就int 3
,于是也把这句改成nop
有了思路,打开OD
在main函数下个断点,跑起程序,修改2个地方的指令
双击指令,会弹框,填上nop
,点击汇编即可。
接下来一直F7运行程序,进入csaw2013.00251000
函数后观察
getit
下载下来是二进制文件直接运行啥也没有,用file查看是64位的,丢到ida64位中分析
观察到整个流程是给一个flag.txt文件中写flag,但是最后把这个文件给删除了,但是如果是写文件的话,在文件流还没关闭的情况下,应该是存在内存中的,所以用gdb调试
值应该是在stream
里面,我这里把断点下在fclose
前面,查看下地址
接下来运行gdb,我断点下在0x04008b9
,看它把rax
付给rdi
,后面备注是stream
,也就是flag值,最后run,直接查看rdi的值,就是flag
maze
下载下来是个二进制文件,题目提示是走迷宫,用ida打开
第一个逻辑是s1
的值从输入端接受, 要求长度为24,前5个字符是ntcf{
,最后个字符是}
接下来就是循环
这里因为前面要求是24个字符,所以第一个if(strlen(&s1)-1 > 5)
肯定过,要想循环接受 v6要为真,但是前循环了了16次,并且上面的sub_400690(asc_601060,HIDWORD(v10),(unsigned int)v10)
要过判定
点进去查看这个函数,表示是 [空格]或者'#' 就返回真,否则返回假,返回假就结束了整个程序
之后对上面4个sub_xxx()函数进行查看,点进去再退出来,函数参数会变得更加准确
之前的v10变成v9了,大致逻辑如下
sub_400650()
输入O
,v9的下一位减一
sub_400660()
输入o
,v9的下一位加一
sub_400670()
输入.
,v9减一
sub_400680()
输入0
,v9加一
最后查看成功的前面一个判定的条件asc_601060[8 * (signed int)v9]+SHIDWORD(v9) != 35
查看下SHIDWORD
的作用https://blog.csdn.net/huiguixian/article/details/52026710
SHIDWORD(V9)
也就是v9的下一位,最后查看下要匹配的字符串asc_601060
的值,直接点进去就行
是一堆符号,又因为题目提示是迷宫,根据sub_400690()
函数中算法取的是v9下一位
+ v9 * 8
的偏移,可以得出迷宫每行是8个字符,把这个字符串赋值出来,手动每8个字符换行
得到迷宫,而最后判断条件是为走到#
,所以最后的思路就很清晰了
O
向左走
o
向右走
.
向上走
0
向下走
*
是墙,#
是目标,[空格]
是路
走完加上nctf{
和}
,刚好24位
最后答案是nctf{o0oo00O000oooo..OO}