Reverse
是我得分第二高的模块。得这么多分,得感谢void
大哥,然后感谢RX
出题人跟我py
……最后还是有三道题没做出来,唉~
还是太菜了,我要继续向void
大哥和RX
师傅学习~
我做出来的
逆向工程入门指北
感谢RX
大神的学习资料,我就收下啦~~
Welcome To Re
拖进IDA64
,找到main
函数,F5
反编译:
moectf{W3lc0me-T0_th3-W0rld_Of_R3v3rsE!}
Thank you Javascript
一般而言,,运行一下,心里舒坦……
但运行出来也没什么用。
混淆???我们查一下,关键字搜索“JS
混淆”:
什么???你没有搜索出来?
别问,问就是你的搜索引擎辣鸡!
混淆后:
eval(function(p, a, c, k, e, d) {
e = function(c) {
return (c < a ? "": e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
};
if (!''.replace(/^/, String)) {
while (c--) d[e(c)] = k[c] || e(c);
k = [function(e) {
return d[e]
}];
e = function() {
return '\\w+'
};
c = 1;
};
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p;
} ('l 1=m(\'k-4-2\');i j 6(){1.2(\'q r p --n o b\');1.2(5 1.4());1.2(`a ${5 1.d(\'9 h e?\')}!`);f 3=g;F(!3){1.2(\'D E 7 B 8:\');3=5 1.4()===\'G{H\'+\'c\'+\'v\'+\'w\'+\'0\'+\'u-\'+\'s\'+\'t\'+\'z\'+\'A\'+\'!}\'}1.2(\'y! x C 7 8!\')}6();', 44, 44, '|io|write|saidHi|read|await|main|the|flag|Who|Hello|Reverier||ask|you|let|false|are|async|function|console|const|require|written|by|ThankYouJavaScript|MoeCTF|2020|Jav|aS||k_|Y|You|Congratulations|cr|ipt|true|find|Please|input|while|moectf|Fx'.split('|'), 0, {}))
解混淆后:
const io=require('console-read-write');
async function main(){
io.write('MoeCTF 2020 ThankYouJavaScript --written by Reverier');
io.write(await io.read());
io.write(`Hello ${await io.ask('Who are you?')}!`);
let saidHi=false;
while(!saidHi)
{
io.write('Please input the true flag:');
saidHi=await
io.read()==='moectf{Fx'+'c'+'k_'+'Y'+'0'+'u-'+'Jav'+'aS'+'cr'+'ipt'+'!}'
}
io.write('Congratulations! You find the flag!')
}main();
moectf{Fxck_Y0u-JavaScript!}
Simple Re
先运行一下:
嗯???竟然不直接给我flag
,把他交给我的女朋友IDA
,让我女朋友来收拾他!!!
发现关键比较!还是我女朋友厉害!!!
思路比较清晰,就是把我们输进去的东西进行一堆异或操作,然后和加密过的flag
比较,也正应了提示:异或异或!
那我们把加密过的flag
抠出来,然后写一个程序的逆向算法就ok了,但是异或怎么逆呢???
性质
1、交换律
2、结合律,即(a ^ b) ^ c == a ^ ( b ^ c)
3、对于任何数x,都有x ^ x=0,x ^ 0=x
4、自反性 A XOR B XOR B = A xor 0 = A
这里利用了异或操作的交换率和自反性
直接贴解密脚本:
#include<bits/stdc++.h>
using namespace std;
int main(int)
{
string aim="rpz|kydKw^qTl@Y/m2f/J-@o^k.,qkb";
for (int i = 0; i <= 30; ++i )
aim[i] ^= 0x17;
for (int j = 0; j <= 30; ++j )
aim[j] ^= 0x39u;
for (int k = 0; k <= 30; ++k )
aim[k] ^= 0x4Bu;
for (int l = 0; l <= 30; ++l )
aim[l] ^= 0x4Au;
for (int m = 0; m <= 30; ++m )
aim[m] ^= 0x49u;
for (int n = 0; n <= 30; ++n )
aim[n] ^= 0x26u;
for (int ii = 0; ii <= 30; ++ii )
aim[ii] ^= 0x15u;
for (int jj = 0; jj <= 30; ++jj )
aim[jj] ^= 0x61u;
for (int kk = 0; kk <= 30; ++kk )
aim[kk] ^= 0x56u;
for (int ll = 0; ll <= 30; ++ll )
aim[ll] ^= 0x1Bu;
for (int mm = 0; mm <= 30; ++mm )
aim[mm] ^= 0x21u;
for (int nn = 0; nn <= 30; ++nn )
aim[nn] ^= 0x40u;
for (int i1 = 0; i1 <= 30; ++i1 )
aim[i1] ^= 0x57u;
for (int i2 = 0; i2 <= 30; ++i2 )
aim[i2] ^= 0x2Eu;
for (int i3 = 0; i3 <= 30; ++i3 )
aim[i3] ^= 0x49u;
for (int i4 = 0; i4 <= 30; ++i4 )
aim[i4] ^= 0x37u;
cout<<aim;
return 0;
}
基本上是从女朋友IDA
那里直接拿的,就加了一点点……
Protection
这个提示已经很明显了,“给程序套一层衣服”=>"壳":
DIE
查一下壳:UPX3.96
,我们直接在github上面找UPX3.96壳的脱壳机进行“脱衣,扒光”:
我这个时候试运行一下:
哼~西内!竟然不直接给我flag
,那你去见见我女朋友吧:
哟西~还是女朋友靠谱!!!程序逻辑很简单,还是异或操作,直接贴解密程序:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string x="aouv#@!V08asdozpnma&*#%!$^&*";
char v5[30];
int y[30]={12,0,16,21,87,38,90,35,64,64,62,66,55,48,9,25,3,29,80,67,7,87,21,126,81,109,67,87};
for (int i = 0; i <= 27; ++i )
v5[i]= y[i] ^ x[i];
cout<<v5;
return 0;
}
moectf{upx_1S_simp1e-t0_u3e}
Real EasyPython
下载下来是.pyc
文件,这个文件可以简单地理解成py
的编译文件,所以我们按照常规思路,我们需要把这个反编译。搜索关键字“Python
反编译”:
可以在第一个网站上在线反编译,也可以在第二个的里面找到工具uncompyle6
,我们这里讲一下python
反编译工具的使用:
pip install uncompyle6
uncompyle6 puzzle.pyc > puzzle_dec.py
我们下来直接看反编译的python
脚本:
key = [
115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35]
print('Input your flag: ', end='')
flag = input()
out = []
for i in flag:
out.append(ord(i) >> 4 ^ ord(i))
if len(out) != len(key):
print('TRY AGAIN!')
exit()
for i in range(len(out)):
if out[i] != key[i]:
print('TRY AGAIN!')
exit()
print('you are right! the flag is : moectf{%s}' % flag)
程序思路很清晰,但是这里有个小点:脚本里面的>>
操作怎么处理呢???直接<<
不就完了。错!因为>>
操作是将该数据转化为二进制然后抹去最后四位;而<<
操作是将该数据转化为二进制,然后直接在最后面补上四个’0’。所以这里的>>
暴力处理一下,上脚本:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int ori[50]={115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35};
char rel[50];
for(int i=0;i<33;i++)
{
for(int j=33;j<127;j++)
if((j>>4^j)==ori[i])
rel[i]=j;
}
cout<<rel;
return 0;
}
# moectf{tH1s_1s_th3-R3a1ly_3asy_Python!}
RxEncode
这个题……直接找我女朋友,我相信我搞不定,必须要找女朋友来帮忙。在IDA
先查一下字符串:
看到那么一串字符串,盲猜换表base64
然后看一看主函数的思路:
程序的思路:
输入
flag
=>“换表base64
”加密=>与程序内部数据对比=>yes/no
那我们的思路就是:
扣出内部数据=>“换表
base64
”解密=>flag
但是我们发现一个问题,就是程序内部的数据竟然不是字符,而是十六进制的形式:
怎么办呢???这里涉及到了另外一个知识点“大小端序”,我们看到的v2、v15、v16、v17
都是小端序存储显示出来的,我们进入hex
窗口或者自己手动dump
出来正常的内容:
\x9A\x87\x9C\xB5\xFE\x58\xD1\x4A\xFE\x0B\xED\x6C\xFA\xFD\xEB\xCB\xE8\x34\xA3\x43\x8E\xA3\x47\x7A
下来就是一个换表base64
的问题了:
import base64
flag_en = b'\x9A\x87\x9C\xB5\xFE\x58\xD1\x4A\xFE\x0B\xED\x6C\xFA\xFD\xEB\xCB\xE8\x34\xA3\x43\x8E\xA3\x47\x7A'
flag = str(base64.b64encode(flag_en)).replace('5', '{').replace('6', '}')
print(flag)
# moectf{Y0Ur+C+1s+v3ry+g0o0OOo0d}
EasyCommonLisp
这个题真是令人头大!!!为了做这个题,还得去学习一下clisp
这门语言
“一名真正的
CTF
选手,应该在15mins
之内学会任何一门语言!!!(傲娇脸)” ——XDSEC_Reverier(RX
题目:
(defparameter +alphabet+"AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs")(defparameter +len+(length +alphabet+))(defun divmod(number divisor)(values(floor(/ number divisor))(mod number divisor)))(defun encode(str)(let((value 0)(rstr(reverse str))(output(make-string-output-stream))(npad 0))(loop for i from 0 to(1- (length str))do(setf value(+ value(*(char-code(elt rstr i))(expt 256 i)))))(loop while(>= value +len+)do(multiple-value-bind(new-value mod)(divmod value +len+)(setf value new-value)(write-char(elt +alphabet+ mod) output)))(write-char(elt +alphabet+ value)output)(loop for char across str do(if(char-equal char #\Nul)(incf npad)(return)))(concatenate 'string(coerce(loop for i from 1 to npad collecting #\1)'string)(reverse(get-output-stream-string output)))))(print(encode "moectf{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"))
;;;; eof
;;;; flag is "&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP"
手动格式化一下:
(defparameter +alphabet+"AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs");
(defparameter +len+(length +alphabet+))
(
defun divmod(number divisor )
(
values(floor(/ number divisor))(mod number divisor)
)
)
(
defun encode(str)
(
let
(
(value 0)
(rstr(reverse str))
(output(make-string-output-stream))
(npad 0)
)
(
loop for i from 0 to(1- (length str))
do
(
setf value
(
+ value(*(char-code(elt rstr i))(expt 256 i))
)
)
)
(
loop while(>= value +len+)
do
(
multiple-value-bind
(new-value mod)
(divmod value +len+)
(setf value new-value)
(write-char(elt +alphabet+ mod) output)
)
)
(
write-char(elt +alphabet+ value)output
)
(
loop for char across str
do
(
if(char-equal char #\Nul)
(incf npad);npad++;
(return)
)
)
(print npad)
(
concatenate 'string(coerce(loop for i from 1 to npad collecting #\1)'string)
(
reverse(get-output-stream-string output)
)
)
)
)
(print(encode "moectf{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"))
;;;; eof
;;;; flag is "&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP"
虽然比题目好看一点,但还是很难看……
这个题的解题过程就是:学会clisp=>读懂题目=>敲成python
=>写逆程序
转换成python
:
alphabet = "AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs"
length = len(alphabet)
def divmod(a,b):
return a//b,a%b
def reverse(s):
return ''.join(reversed(s))
def encode(str):
ans=""
value = 0
rstr = reverse(str)
napd = 0
for i in range(0,len(str)):
value = value + ord(rstr[i])*(256**i)
while value>=length:
value, mod = divmod(value, length)
ans=ans+alphabet[mod]
ans=ans+alphabet[value]
ans=reverse(ans)
return ans
print(encode("moectf{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"))
#"&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP"
然后写一下解密脚本:
alphabet = "AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs"
ans = "&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP"
def reverse(s):
return ''.join(reversed(s))
ans = reverse(ans)
value = alphabet.find(ans[len(ans)-1])
for i in range(0,58):
value = len(alphabet)*value + alphabet.find(ans[len(ans)-2-i])
a = hex(value)
flag = str(a)
flag = flag[2:len(flag)-1]
print(flag.decode('hex'))
# moectf{woO0Oow_Y0u-ar3_th3_g0D_0f_LIIIISP!}
对了,解密脚本是python2
写的,因为在python3
环境下会有str
和bytes
两种数据类型之间奇奇怪怪的错误……
EzJava
据名字猜考点:java
逆向。
先找java
逆向工具,这里我用的是jd.gui
,把题目拖进去就可以看到java
代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class EasyJava {
public static void main(String[] paramArrayOfString) {
System.out.println("MoeCTF 2020 EasyJava --by Reverier");
System.out.println("Input your flag and I will check it:");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String str = null;
int[] arrayOfInt = {
43, 23, 23, 62, 110, 66, 94, 99, 126, 68,
43, 62, 76, 110, 22, 5, 15, 111, 86, 75,
78, 83, 86, 0, 85, 86 };
try {
str = bufferedReader.readLine();
} catch (Exception exception) {
System.out.println("ERROR: Undefined Exception.");
}
if (str.isEmpty()) {
System.out.println("Nothing received.");
} else {
if (str.length() != 35) { //flag长度35
System.out.println("Rua~~~Wrong!");
return;
}
String str1 = str.substring(0, 7);
if (!str1.equals("moectf{")) {
System.out.println("Rua~~~Wrong!");
return;
}
String str2 = str.substring(7, str.length() - 1); //把flag的头"moectf{"和最后面的"}"脱掉
//核心代码段
for (byte b = 0; b < str2.length() - 1; b++) {
char c1 = str2.charAt(b);
char c2 = str2.charAt(b + 1);
int i = c1 ^ c2;
if (i != arrayOfInt[b]) {
System.out.println("Rua~~~Wrong!");
return;
}
}
System.out.println("Congratulations!");
}
}
}
我们只需要仔细看核心代码段,又是异或……自反性,搞他!!!
因为flag
一共35位,掐头去尾还剩27位,但是它内部数据只有26位,所以我们没有办法逆向搞并且flag
是有意义字符串,所以这里还是选择正向暴力!!!
暴力出奇迹,打表得省一
#include<bits/stdc++.h>
using namespace std;
int main()
{
int b[50]={43,23,23,62,110,66,94,99,126,68,43,62,76,110,22,5,15,111,86,75,78,83,86,0,85,86};
for(int n=32;n<=126;n++)
{
char rel[100];
rel[0]=n;
for(int i=0;i<26;i++)
rel[i+1]=b[i]^rel[i];
cout<<rel<<"\n";
}
return 0;
}
moectf{Java_1s-N0t_a-CUP_0f-c0ff3e}
RollCall
这个题比较特殊……
不管是题干还是hint
都在暗示我们一件事情这程序不能逆向!!!我们看一下这个程序包里面有什么???
嗯?.sqlite
文件???这是一个数据库文件,那我们就可以猜到学生的各项数据他是存储在数据库里面,我们如果不能在程序添加性别为2,那我们可以直接对数据库操作。我是打开了wsl
然后装一个 sqlite
数据库,用insert
命令向数据库里面插入一条性别为2的信息:
sudo apt install sqlite3
sqlite3 UserData
.tables //查看该库下面的表,获取该库下表:students
PRAGMA table_info(students);//查看students表下所有字段:ID,name,sex,averange
INSERT INTO students VALUES (233, 'BlackBird', 2, 2 );
然后再打开程序:
MidPython
emmmm……pyc
文件逆向先反编译,还是上面的那个uncompyle6
,但是,报错了???我们打开“半生半熟”(一半py一半字节码)的py
文件:(超长代码警告!!!)
# uncompyle6 version 3.7.3
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)]
# Embedded file name: ./EzPython/source.py
# Compiled at: 2020-07-25 16:57:06
# Size of source mod 2**32: 5784 bytes
Instruction context:
L. 76 414 JUMP_BACK 32 'to 32'
-> 416 JUMP_FORWARD 430 'to 430'
418_0 COME_FROM 60 '60'
Instruction context:
L. 118 414 JUMP_BACK 32 'to 32'
-> 416 JUMP_FORWARD 430 'to 430'
418_0 COME_FROM 60 '60'
T_letter = ['', '', '', '', '']
def Create_Matrix(key):
key = Remove_Duplicates(key)
key = key.replace(' ', '')
j = 0
for i in range(len(key)):
T_letter[j] += key[i]
if 0 == (i + 1) % 5:
j += 1
def Remove_Duplicates(key):
key = key.upper()
_key = ''
for ch in key:
if ch == 'I':
ch = 'J'
if ch in _key:
continue
else:
_key += ch
return _key
def Get_MatrixIndex(ch):
for i in range(len(T_letter)):
for j in range(len(T_letter)):
if ch == T_letter[i][j]:
return (
i, j)
def Encrypt--- This code section failed: ---
L. 44 0 LOAD_STR ''
2 STORE_FAST 'ciphertext'
L. 46 4 LOAD_GLOBAL len
6 LOAD_FAST 'plaintext'
8 CALL_FUNCTION_1 1 ''
10 LOAD_CONST 2
12 BINARY_MODULO
14 LOAD_CONST 0
16 COMPARE_OP !=
18 POP_JUMP_IF_FALSE 28 'to 28'
L. 47 20 LOAD_FAST 'plaintext'
22 LOAD_STR 'Z'
24 INPLACE_ADD
26 STORE_FAST 'plaintext'
28_0 COME_FROM 18 '18'
L. 49 28 LOAD_CONST 0
30 STORE_FAST 'i'
L. 50 32 LOAD_FAST 'i'
34 LOAD_GLOBAL len
36 LOAD_FAST 'plaintext'
38 CALL_FUNCTION_1 1 ''
40 COMPARE_OP <
42_44 POP_JUMP_IF_FALSE 440 'to 440'
L. 51 46 LOAD_CONST True
48 LOAD_FAST 'plaintext'
50 LOAD_FAST 'i'
52 BINARY_SUBSCR
54 LOAD_METHOD isalpha
56 CALL_METHOD_0 0 ''
58 COMPARE_OP ==
60_62 POP_JUMP_IF_FALSE 418 'to 418'
L. 52 64 LOAD_FAST 'i'
66 LOAD_CONST 1
68 BINARY_ADD
70 STORE_FAST 'j'
L. 53 72 LOAD_FAST 'j'
74 LOAD_GLOBAL len
76 LOAD_FAST 'plaintext'
78 CALL_FUNCTION_1 1 ''
80 COMPARE_OP <
82_84 POP_JUMP_IF_FALSE 406 'to 406'
L. 54 86 LOAD_CONST True
88 LOAD_FAST 'plaintext'
90 LOAD_FAST 'j'
92 BINARY_SUBSCR
94 LOAD_METHOD isalpha
96 CALL_METHOD_0 0 ''
98 COMPARE_OP ==
100_102 POP_JUMP_IF_FALSE 396 'to 396'
L. 55 104 LOAD_STR 'I'
106 LOAD_FAST 'plaintext'
108 LOAD_FAST 'i'
110 BINARY_SUBSCR
112 LOAD_METHOD upper
114 CALL_METHOD_0 0 ''
116 COMPARE_OP ==
118 POP_JUMP_IF_FALSE 130 'to 130'
L. 56 120 LOAD_GLOBAL Get_MatrixIndex
122 LOAD_STR 'J'
124 CALL_FUNCTION_1 1 ''
126 STORE_FAST 'x'
128 JUMP_FORWARD 146 'to 146'
130_0 COME_FROM 118 '118'
L. 58 130 LOAD_GLOBAL Get_MatrixIndex
L. 59 132 LOAD_FAST 'plaintext'
134 LOAD_FAST 'i'
136 BINARY_SUBSCR
138 LOAD_METHOD upper
140 CALL_METHOD_0 0 ''
L. 58 142 CALL_FUNCTION_1 1 ''
144 STORE_FAST 'x'
146_0 COME_FROM 128 '128'
L. 60 146 LOAD_STR 'I'
148 LOAD_FAST 'plaintext'
150 LOAD_FAST 'j'
152 BINARY_SUBSCR
154 LOAD_METHOD upper
156 CALL_METHOD_0 0 ''
158 COMPARE_OP ==
160 POP_JUMP_IF_FALSE 172 'to 172'
L. 61 162 LOAD_GLOBAL Get_MatrixIndex
164 LOAD_STR 'J'
166 CALL_FUNCTION_1 1 ''
168 STORE_FAST 'y'
170 JUMP_FORWARD 188 'to 188'
172_0 COME_FROM 160 '160'
L. 63 172 LOAD_GLOBAL Get_MatrixIndex
174 LOAD_FAST 'plaintext'
176 LOAD_FAST 'j'
178 BINARY_SUBSCR
180 LOAD_METHOD upper
182 CALL_METHOD_0 0 ''
184 CALL_FUNCTION_1 1 ''
186 STORE_FAST 'y'
188_0 COME_FROM 170 '170'
L. 65 188 LOAD_FAST 'x'
190 LOAD_CONST 0
192 BINARY_SUBSCR
194 LOAD_FAST 'y'
196 LOAD_CONST 0
198 BINARY_SUBSCR
200 COMPARE_OP ==
202_204 POP_JUMP_IF_FALSE 268 'to 268'
L. 66 206 LOAD_FAST 'ciphertext'
208 LOAD_FAST 'T_letter'
210 LOAD_FAST 'x'
212 LOAD_CONST 0
214 BINARY_SUBSCR
216 BINARY_SUBSCR
218 LOAD_FAST 'x'
220 LOAD_CONST 1
222 BINARY_SUBSCR
224 LOAD_CONST 1
226 BINARY_ADD
L. 67 228 LOAD_CONST 5
L. 66 230 BINARY_MODULO
232 BINARY_SUBSCR
L. 67 234 LOAD_FAST 'T_letter'
236 LOAD_FAST 'y'
238 LOAD_CONST 0
240 BINARY_SUBSCR
242 BINARY_SUBSCR
244 LOAD_FAST 'y'
246 LOAD_CONST 1
248 BINARY_SUBSCR
250 LOAD_CONST 1
252 BINARY_ADD
254 LOAD_CONST 5
256 BINARY_MODULO
258 BINARY_SUBSCR
L. 66 260 BINARY_ADD
262 INPLACE_ADD
264 STORE_FAST 'ciphertext'
266 JUMP_ABSOLUTE 406 'to 406'
268_0 COME_FROM 202 '202'
L. 68 268 LOAD_FAST 'x'
270 LOAD_CONST 1
272 BINARY_SUBSCR
274 LOAD_FAST 'y'
276 LOAD_CONST 1
278 BINARY_SUBSCR
280 COMPARE_OP ==
282_284 POP_JUMP_IF_FALSE 348 'to 348'
L. 69 286 LOAD_FAST 'ciphertext'
288 LOAD_FAST 'T_letter'
290 LOAD_FAST 'x'
292 LOAD_CONST 1
294 BINARY_SUBSCR
296 LOAD_CONST 1
298 BINARY_ADD
L. 70 300 LOAD_CONST 5
L. 69 302 BINARY_MODULO
304 BINARY_SUBSCR
L. 70 306 LOAD_FAST 'x'
308 LOAD_CONST 0
310 BINARY_SUBSCR
L. 69 312 BINARY_SUBSCR
L. 70 314 LOAD_FAST 'T_letter'
316 LOAD_FAST 'y'
318 LOAD_CONST 1
320 BINARY_SUBSCR
322 LOAD_CONST 1
324 BINARY_ADD
326 LOAD_CONST 5
328 BINARY_MODULO
330 BINARY_SUBSCR
332 LOAD_FAST 'y'
334 LOAD_CONST 0
336 BINARY_SUBSCR
338 BINARY_SUBSCR
L. 69 340 BINARY_ADD
342 INPLACE_ADD
344 STORE_FAST 'ciphertext'
346 JUMP_ABSOLUTE 406 'to 406'
348_0 COME_FROM 282 '282'
L. 72 348 LOAD_FAST 'ciphertext'
350 LOAD_FAST 'T_letter'
352 LOAD_FAST 'x'
354 LOAD_CONST 0
356 BINARY_SUBSCR
358 BINARY_SUBSCR
360 LOAD_FAST 'y'
362 LOAD_CONST 1
364 BINARY_SUBSCR
366 BINARY_SUBSCR
368 LOAD_FAST 'T_letter'
370 LOAD_FAST 'y'
372 LOAD_CONST 0
374 BINARY_SUBSCR
376 BINARY_SUBSCR
378 LOAD_FAST 'x'
380 LOAD_CONST 1
382 BINARY_SUBSCR
384 BINARY_SUBSCR
386 BINARY_ADD
388 INPLACE_ADD
390 STORE_FAST 'ciphertext'
L. 73 392_394 BREAK_LOOP 406 'to 406'
396_0 COME_FROM 100 '100'
L. 74 396 LOAD_FAST 'j'
398 LOAD_CONST 1
400 INPLACE_ADD
402 STORE_FAST 'j'
404 JUMP_BACK 72 'to 72'
406_0 COME_FROM 82 '82'
L. 75 406 LOAD_FAST 'j'
408 LOAD_CONST 1
410 BINARY_ADD
412 STORE_FAST 'i'
L. 76 414 JUMP_BACK 32 'to 32'
416 JUMP_FORWARD 430 'to 430'
418_0 COME_FROM 60 '60'
L. 78 418 LOAD_FAST 'ciphertext'
420 LOAD_FAST 'plaintext'
422 LOAD_FAST 'i'
424 BINARY_SUBSCR
426 INPLACE_ADD
428 STORE_FAST 'ciphertext'
430_0 COME_FROM 416 '416'
L. 79 430 LOAD_FAST 'i'
432 LOAD_CONST 1
434 INPLACE_ADD
436 STORE_FAST 'i'
438 JUMP_BACK 32 'to 32'
440_0 COME_FROM 42 '42'
L. 81 440 LOAD_FAST 'ciphertext'
442 RETURN_VALUE
-1 RETURN_LAST
Parse error at or near `JUMP_FORWARD' instruction at offset 416
def Decrypt--- This code section failed: ---
L. 87 0 LOAD_STR ''
2 STORE_FAST 'plaintext'
L. 88 4 LOAD_GLOBAL len
6 LOAD_FAST 'ciphertext'
8 CALL_FUNCTION_1 1 ''
10 LOAD_CONST 2
12 BINARY_MODULO
14 LOAD_CONST 0
16 COMPARE_OP !=
18 POP_JUMP_IF_FALSE 28 'to 28'
L. 89 20 LOAD_FAST 'ciphertext'
22 LOAD_STR 'Z'
24 INPLACE_ADD
26 STORE_FAST 'ciphertext'
28_0 COME_FROM 18 '18'
L. 91 28 LOAD_CONST 0
30 STORE_FAST 'i'
L. 92 32 LOAD_FAST 'i'
34 LOAD_GLOBAL len
36 LOAD_FAST 'ciphertext'
38 CALL_FUNCTION_1 1 ''
40 COMPARE_OP <
42_44 POP_JUMP_IF_FALSE 440 'to 440'
L. 93 46 LOAD_CONST True
48 LOAD_FAST 'ciphertext'
50 LOAD_FAST 'i'
52 BINARY_SUBSCR
54 LOAD_METHOD isalpha
56 CALL_METHOD_0 0 ''
58 COMPARE_OP ==
60_62 POP_JUMP_IF_FALSE 418 'to 418'
L. 94 64 LOAD_FAST 'i'
66 LOAD_CONST 1
68 BINARY_ADD
70 STORE_FAST 'j'
L. 95 72 LOAD_FAST 'j'
74 LOAD_GLOBAL len
76 LOAD_FAST 'ciphertext'
78 CALL_FUNCTION_1 1 ''
80 COMPARE_OP <
82_84 POP_JUMP_IF_FALSE 406 'to 406'
L. 96 86 LOAD_CONST True
88 LOAD_FAST 'ciphertext'
90 LOAD_FAST 'j'
92 BINARY_SUBSCR
94 LOAD_METHOD isalpha
96 CALL_METHOD_0 0 ''
98 COMPARE_OP ==
100_102 POP_JUMP_IF_FALSE 396 'to 396'
L. 97 104 LOAD_STR 'I'
106 LOAD_FAST 'ciphertext'
108 LOAD_FAST 'i'
110 BINARY_SUBSCR
112 LOAD_METHOD upper
114 CALL_METHOD_0 0 ''
116 COMPARE_OP ==
118 POP_JUMP_IF_FALSE 130 'to 130'
L. 98 120 LOAD_GLOBAL Get_MatrixIndex
122 LOAD_STR 'J'
124 CALL_FUNCTION_1 1 ''
126 STORE_FAST 'x'
128 JUMP_FORWARD 146 'to 146'
130_0 COME_FROM 118 '118'
L. 100 130 LOAD_GLOBAL Get_MatrixIndex
L. 101 132 LOAD_FAST 'ciphertext'
134 LOAD_FAST 'i'
136 BINARY_SUBSCR
138 LOAD_METHOD upper
140 CALL_METHOD_0 0 ''
L. 100 142 CALL_FUNCTION_1 1 ''
144 STORE_FAST 'x'
146_0 COME_FROM 128 '128'
L. 102 146 LOAD_STR 'I'
148 LOAD_FAST 'ciphertext'
150 LOAD_FAST 'j'
152 BINARY_SUBSCR
154 LOAD_METHOD upper
156 CALL_METHOD_0 0 ''
158 COMPARE_OP ==
160 POP_JUMP_IF_FALSE 172 'to 172'
L. 103 162 LOAD_GLOBAL Get_MatrixIndex
164 LOAD_STR 'J'
166 CALL_FUNCTION_1 1 ''
168 STORE_FAST 'y'
170 JUMP_FORWARD 188 'to 188'
172_0 COME_FROM 160 '160'
L. 105 172 LOAD_GLOBAL Get_MatrixIndex
174 LOAD_FAST 'ciphertext'
176 LOAD_FAST 'j'
178 BINARY_SUBSCR
180 LOAD_METHOD upper
182 CALL_METHOD_0 0 ''
184 CALL_FUNCTION_1 1 ''
186 STORE_FAST 'y'
188_0 COME_FROM 170 '170'
L. 107 188 LOAD_FAST 'x'
190 LOAD_CONST 0
192 BINARY_SUBSCR
194 LOAD_FAST 'y'
196 LOAD_CONST 0
198 BINARY_SUBSCR
200 COMPARE_OP ==
202_204 POP_JUMP_IF_FALSE 268 'to 268'
L. 108 206 LOAD_FAST 'plaintext'
208 LOAD_FAST 'T_letter'
210 LOAD_FAST 'x'
212 LOAD_CONST 0
214 BINARY_SUBSCR
216 BINARY_SUBSCR
218 LOAD_FAST 'x'
220 LOAD_CONST 1
222 BINARY_SUBSCR
224 LOAD_CONST 1
226 BINARY_SUBTRACT
L. 109 228 LOAD_CONST 5
L. 108 230 BINARY_MODULO
232 BINARY_SUBSCR
L. 109 234 LOAD_FAST 'T_letter'
236 LOAD_FAST 'y'
238 LOAD_CONST 0
240 BINARY_SUBSCR
242 BINARY_SUBSCR
244 LOAD_FAST 'y'
246 LOAD_CONST 1
248 BINARY_SUBSCR
250 LOAD_CONST 1
252 BINARY_SUBTRACT
254 LOAD_CONST 5
256 BINARY_MODULO
258 BINARY_SUBSCR
L. 108 260 BINARY_ADD
262 INPLACE_ADD
264 STORE_FAST 'plaintext'
266 JUMP_ABSOLUTE 406 'to 406'
268_0 COME_FROM 202 '202'
L. 110 268 LOAD_FAST 'x'
270 LOAD_CONST 1
272 BINARY_SUBSCR
274 LOAD_FAST 'y'
276 LOAD_CONST 1
278 BINARY_SUBSCR
280 COMPARE_OP ==
282_284 POP_JUMP_IF_FALSE 348 'to 348'
L. 111 286 LOAD_FAST 'plaintext'
288 LOAD_FAST 'T_letter'
290 LOAD_FAST 'x'
292 LOAD_CONST 1
294 BINARY_SUBSCR
296 LOAD_CONST 1
298 BINARY_SUBTRACT
L. 112 300 LOAD_CONST 5
L. 111 302 BINARY_MODULO
304 BINARY_SUBSCR
L. 112 306 LOAD_FAST 'x'
308 LOAD_CONST 0
310 BINARY_SUBSCR
L. 111 312 BINARY_SUBSCR
L. 112 314 LOAD_FAST 'T_letter'
316 LOAD_FAST 'y'
318 LOAD_CONST 1
320 BINARY_SUBSCR
322 LOAD_CONST 1
324 BINARY_SUBTRACT
326 LOAD_CONST 5
328 BINARY_MODULO
330 BINARY_SUBSCR
332 LOAD_FAST 'y'
334 LOAD_CONST 0
336 BINARY_SUBSCR
338 BINARY_SUBSCR
L. 111 340 BINARY_ADD
342 INPLACE_ADD
344 STORE_FAST 'plaintext'
346 JUMP_ABSOLUTE 406 'to 406'
348_0 COME_FROM 282 '282'
L. 114 348 LOAD_FAST 'plaintext'
350 LOAD_FAST 'T_letter'
352 LOAD_FAST 'x'
354 LOAD_CONST 0
356 BINARY_SUBSCR
358 BINARY_SUBSCR
360 LOAD_FAST 'y'
362 LOAD_CONST 1
364 BINARY_SUBSCR
366 BINARY_SUBSCR
368 LOAD_FAST 'T_letter'
370 LOAD_FAST 'y'
372 LOAD_CONST 0
374 BINARY_SUBSCR
376 BINARY_SUBSCR
378 LOAD_FAST 'x'
380 LOAD_CONST 1
382 BINARY_SUBSCR
384 BINARY_SUBSCR
386 BINARY_ADD
388 INPLACE_ADD
390 STORE_FAST 'plaintext'
L. 115 392_394 BREAK_LOOP 406 'to 406'
396_0 COME_FROM 100 '100'
L. 116 396 LOAD_FAST 'j'
398 LOAD_CONST 1
400 INPLACE_ADD
402 STORE_FAST 'j'
404 JUMP_BACK 72 'to 72'
406_0 COME_FROM 82 '82'
L. 117 406 LOAD_FAST 'j'
408 LOAD_CONST 1
410 BINARY_ADD
412 STORE_FAST 'i'
L. 118 414 JUMP_BACK 32 'to 32'
416 JUMP_FORWARD 430 'to 430'
418_0 COME_FROM 60 '60'
L. 120 418 LOAD_FAST 'plaintext'
420 LOAD_FAST 'ciphertext'
422 LOAD_FAST 'i'
424 BINARY_SUBSCR
426 INPLACE_ADD
428 STORE_FAST 'plaintext'
430_0 COME_FROM 416 '416'
L. 121 430 LOAD_FAST 'i'
432 LOAD_CONST 1
434 INPLACE_ADD
436 STORE_FAST 'i'
438 JUMP_BACK 32 'to 32'
440_0 COME_FROM 42 '42'
L. 123 440 LOAD_FAST 'plaintext'
442 RETURN_VALUE
-1 RETURN_LAST
Parse error at or near `JUMP_FORWARD' instruction at offset 416
if __name__ == '__main__':
key = 'YWCNOPJAFGHDTULMQXZEBRVKS'
flag_enc = 'WYTFSQOYGYOQKJLHUE'
Create_Matrix(key)
print('Please Input flag: ')
plaintext = input()
if plaintext[0:7] != 'moectf{' or plaintext[(-1)] != '}':
print('Ruaaaaa~Wrong!')
input()
exit()
else:
plaintext = plaintext[7:-1]
flag = Encrypt(plaintext, T_letter)
if flag != flag_enc:
print('Ruaaaaa~Wrong!')
input()
exit()
else:
print('Congratulations!')
input()
exit()
看着这“夹生”的代码,我内心反复着mmp~~~
但是突然有个点:两个没有完全解析的函数Encrypt、Decrypt
……等下!!!Decrypt
函数给出来了?那我们拿着解密函数不用不是对不起它么:
import puzzle
key = 'YWCNOPJAFGHDTULMQXZEBRVKS'
cipher = 'WYTFSQOYGYOQKJLHUE'
puzzle.Create_Matrix(key)
print(puzzle.T_letter)
print(puzzle.Decrypt(cipher,puzzle.T_letter))
en???这么简单???就是这么简单……想不到吧~~~
啦啦啦啦啦啦~~~
Flower
这个题讲真好难!!!这里先感谢一下void
大神对我的指导,void
永远是我大哥!!!
好了,下来开始正题:
根据题目名称flower
,盲猜本题考查花指令,拖进IDA
分析,扣符号表死马……F12
查看字符串,这里有一个小点,就是我们要让我们的IDA显示中文字符。根据字符串定位main
函数:
F5
大法,然后稍微改一改变量名(这样子,能舒服一些……找到对数据处理的函数:
经过这一部分处理后的结果和byte_4032AC
进行比较:
跟进off_4032A4
:
分别跟进两个函数,发现loc_401310
存在花指令:
我们手动patch
一下,把40133B
修改成nop
:点在40133B
,按U
,切换到hex-view
,F2
修改74
为90
,F2
保存,切换回IDA view
,按C
,点击401310
,按P
:
这个函数等效于:
for(int i=0;i<16;i++)
input[i] = 16 * (inpout[result] ^ 0x16) | ((inpout[result] ^ 0x16) >> 4);
然后我们跟进sub_4011B0
:
然后查看off_404018
:
跟进loc_4012B0
,发现花指令,和之前的那个一样,按照上面说的处理:
跟进loc_401240
,也是花指令,处理掉:
跟进loc_401270
,还是花指令,处理掉:
我们现在相当于是把整个程序分析差不多了,我们现在理一下程序的思路:主函数调用func1(loc_401310)、func2(sub_4011B0);func2又调用fun0(sub_4012B0)、fun1(sub_401240)、fun2(sub_401270)
;func2
又返回sub_4012D0
函数。最后再跟byte_4032AC
比较。我们现在需要弄清sub_4012D0
函数在干什么,先试着用IDA
分析一下:
貌似不太行……我们改动态调试:
F9
开始运行,输入0123456789abcdef
,在断点处记录数据:
得知这个函数就是在挨个异或,每一位对应异或的内容是77,76,71,80,75,70,67,74,69,78,73,72,68,66,65。我们现在就可以写一个流程一样的程序,便于我们理解(便于写暴力,狗头.jpg
#include<bits/stdc++.h>
using namespace std;
unsigned char input[20];
int rel[20]={62,254,153,118,139,220,13,24,50,120,111,191,67,116,51,115};
void fun0(int x1,int x2)
{
input[x1] += x2;
return;
}
void fun1(int x1,int x2)
{
input[x1] ^=input[x2];
return;
}
void fun2(int x1,int x2)
{
input[x1] = abs(input[x1]-input[x2]);
return;
}
void func1()
{
for(int i=0;i<16;i++)
{
input[i] = 16 * (input[i] ^ 0x16) | ((input[i] ^ 0x16) >> 4);
}
return;
}
void func2()
{
fun0(0,1);
fun1(1,2);
fun2(2,3);
fun1(3,4);
fun2(4,5);
fun0(5,6);
fun0(6,7);
input[0]^=0x4D;
input[1]^=0x4C;
input[2]^=0x47;
input[3]^=0x50;
input[4]^=0x4B;
input[5]^=0x46;
input[6]^=0x43;
input[7]^=0x4A;
input[8]^=0x45;
input[9]^=0x4E;
input[10]^=0x49;
input[11]^=0x48;
input[12]^=0x44;
input[13]^=0x42;
input[14]^=0x41;
return;
}
int main()
{
cin>>input;
if(strlen(input)<16)
return 0;
func1();
func2();
for(int i=0;i<16;i++)
if(input[i]!=rel[i])
return 0;
cout<<"you're right";
return 0;
}
现在的话如果懒得逆向,你可以试试暴力,16位,你加油(狗头
我们现在逆向一下就ok
了,没什么说的了,直接贴脚本:
#include<bits/stdc++.h>
using namespace std;
unsigned char ori[20]={62,254,153,118,139,220,13,24,50,120,111,191,67,116,51,115};
unsigned char input[20];
void ini()
{
for(int i=0;i<16;i++)
input[i]=ori[i];
return;
}
int main()
{
unsigned char ori[20]={62,254,153,118,139,220,13,24,50,120,111,191,67,116,51,115};
unsigned char input[20];
for(int i=0;i<16;i++)
input[i]=ori[i];
input[0]^=0x4D;
input[1]^=0x4C;
input[2]^=0x47;
input[3]^=0x50;
input[4]^=0x4B;
input[5]^=0x46;
input[6]^=0x43;
input[7]^=0x4A;
input[8]^=0x45;
input[9]^=0x4E;
input[10]^=0x49;
input[11]^=0x48;
input[12]^=0x44;
input[13]^=0x42;
input[14]^=0x41;
input[6]-=7;
input[5]-=6;
input[0] -= 1;
for(int i=0;i<16;i++)
ori[i]=input[i];
input[4] += input[5];
input[3] ^=input[4];
input[2] = input[3]-input[2];
input[1] ^=input[2];
for(int k=0;k<16;k++)
{
input[k] = (16 * input[k] | (input[k] >> 4));
input[k] ^= 0x16;
cout<<input[k];
}
cout<<"\n\n";
return 0;
}
对了,忘记说了。如果IDA
里面显示的是unsigned char
,你的程序也一定要用unsigned char
,尤其是程序中间的处理涉及位运算。