CTF-Re

CTF逆向记录

常见汇编指令记录

  1. SHLSHR

SHL 左移指令使目的操作数逻辑左移一位,最低位用0填充,最高位移入进位标志位,而进位标志位中原来的数值被丢弃

SHR 右移指令使目的操作数逻辑右移一位,最高位用0填充,最低位移入进位标志位,而进位标志位中原来的数值被丢弃

  1. SALSAR

SAL 算术左移指令与SHL指令相同

SAR 算术右移指令将目的操作数进行算术右移

SAR会根据最高位是否为1来拓展符号位

假设AX=1000 0000,SAR AX 1,AX=1100 0000


0xE8:CALL

0x90:NOP


test eax,eax

test逻辑与运算结果为零,就把ZF(零标志)置1

eax=0时,置z标志位为1,jz跳转,jnz不跳转

eax=1时,置z标志位为0,jz不跳转,jnz跳转

cmp eax,eax

cmp算术减法运算结果为零,就把ZF(零标志)置1

eax=0时,置z标志位为1,jz跳转,jnz不跳转

eax=1时,置z标志位为1,jz跳转,jnz不跳转

test相当于两个参数做逻辑与运算,cmp相当与两个参数做减法运算

如果结果为0就置z标志位为1,如果结果不为0就置z标志位为0

当z标志位为1时,jz跳转,jnz不跳转

当z标志位为0时,jz不跳转,jnz跳转

jz:结果为0时跳转

jnz:结果不为0时跳转

常用脚本

base64改表

1
2
3
4
5
6
import base64
a = "R9Ly6NoJvsIPnWhETYtHe4Sdl+MbGujaZpk102wKCr7/ODg5zXAFqQfxBicV3m8U"
b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
base_fix = "+wXp+xDkldnFdFNFdxnzdFWpGx2m"
table = ''.maketrans(a, b)
print(base64.b64decode(base_fix.translate(table)))
1
b'flag{bas3_1s_s0_3asy}'

z3求解器

https://github.com/Z3Prover/z3

安装

pip install z3-solver

常用数据类型

Int:整数(数学意义上)

Bool:布尔型

Array:数组

BitVec('x',n):n位整型,例如:char类型可被设置为Bitvec('x',8)

常用API

Solver():创建一个通用求解器,创建后我们可以添加我们的约束条件,进行下一步的求解

add():添加约束条件,通常在solver()命令之后,添加的约束条件通常是一个逻辑等式

check():通常用来判断在添加完约束条件后,来检测解的情况,有解的时候会回显sat,无解的时候会回显unsat

model():在存在解的时候,该函数会将每个限制条件所对应的解集取交集,进而得出正解

解题记录

https://drive.misaka.gq/CTF_Re/

32c3ctf-2015

libdroid

通过jadx得到部分代码,同时通过ida反编译so文件得到原生函数代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package ctf.stratumauhhur.libdroid;

import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.view.View;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class a extends AppCompatActivity {
static String a = a(getOperatingSystem(), 1);//0x10 0xF4 0x52 0xB2 0x1F 0xF9 0x55 0xFA 0x13 0xFC
static String b = a(getPhoneNumber(), 1);//0x11 0xF7 0x5D 0xB6 0x1A 0xFF 0x19 0xFF 0x1C 0xF7 0x0C 0xE9
static String c = a(installRootkit(), 1);//0x30 0xF4 0x52 0xB3 0x04 0xFF 0x0F 0xE6 0x11 0xF4
static String d = a(generateConfusion(), 1);//0x53 0xAA 0x0E 0xE7 0x42 0xAB 0x4D 0xA4 0x45 0xAC 0x50
static Object f = a(obtainWorldDomination(), 1);//0x18 0xFE 0x45 0xE9
static String flag = a(getFlag(), 1);//0x20 0xF4 0x4E 0xA6 0x0F 0xBE 0x15 0xFC 0x5D 0xE7 0x0F 0xE7 0x02 0xF5 0x19 0xEC 0x5B 0xF5 0x11 0xE4 0x1C 0xAD 0x0F 0xFD 0x47 0xB5 0x52
static String g = a(installiOS(), 1);//0x01 0xF4 0x53 0xA0 0x1D 0xF7 0x0F 0xAE
/*
上述静态函数均为(string,int)类型,调用了static String a(String a2, int b2)这个函数
a="config.ini"
b="blablablabla"
c="Congratula"
d=" 1234567890"
f="key="
flag="Sorry no rootkit for you :("
file_name="rootkit="
然后跳转到onCreate函数
*/
String e;

public static native String generateConfusion();

public static native String getFlag();

public static native String getOperatingSystem();

public static native String getPhoneNumber();

public static native String installRootkit();

public static native String installiOS();

public static native String obtainWorldDomination();

private static native void phoneHome(byte[] bArr, byte[] bArr2);

/* access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
try {
a(a);//public void a(String a2) throws Exception,a="config.ini"
} catch (Exception e2) {
}
this.e = "";
}

/* access modifiers changed from: package-private */
public byte[] a(byte[] a0, String a1) {
byte[] a2 = new byte[a0.length];
for (char a3 = 0; a3 < a2.length; a3 = (char) (a3 + 1)) {
a2[a3] = (byte) (a0[a3] ^ a1.charAt(a3 % a1.length()));
}
return a2;
}

public void a(View v) {//点击按钮,触发事件
//d=" 1234567890"
if (v.getId() == R.id.button) {
this.e += d.charAt(1);
}
if (v.getId() == R.id.button2) {
this.e += d.charAt(2);
}
if (v.getId() == R.id.button3) {
this.e += d.charAt(3);
}
if (v.getId() == R.id.button4) {
this.e += d.charAt(4);
}
if (v.getId() == R.id.button5) {
this.e += d.charAt(5);
}
if (v.getId() == R.id.button6) {
this.e += d.charAt(6);
}
if (v.getId() == R.id.button7) {
this.e += d.charAt(7);
}
if (v.getId() == R.id.button8) {
this.e += d.charAt(8);
}
if (v.getId() == R.id.button9) {
this.e += d.charAt(9);
}
if (v.getId() == R.id.button10) {
this.e += d.charAt(0);
}
if (this.e.length() == 6 || v.getId() == R.id.button11) {
String flag2 = flag;
try {
InputStream b2 = getAssets().open(g);//打开"assets/a/d/c/c"
ByteArrayOutputStream b22 = new ByteArrayOutputStream();
byte[] data = new byte[16384];
while (true) {
int nRead = b2.read(data, 0, data.length);
if (nRead == -1) {
break;
}
b22.write(data, 0, nRead);
}
b22.flush();
byte[] j = b22.toByteArray();
/*j=FEA0AD802059AB12D7C39C88FA2C1DFC81460DDCE9CECC5778F5415F520236D53318663A4026E86EB6CD72B73C0166B14F9923639577346169F6A953403741434F98952C7A273C98681A88A8B785BB154F1A014DC9C89B7578577F980DD851A822B95E594D714F1A81A9BF0729EDFD83*/
byte[] f_ = new byte[16];
System.arraycopy((byte[]) f, 0, f_, 0, ((byte[]) f).length);
System.arraycopy(this.e.getBytes(), 0, f_, 10, this.e.getBytes().length);
/*f_的前十个为b'!\x00\x86\xb7\xff\x86]\x06-0',后六个为按钮代表的字符*/
phoneHome(j, f_);//根据phoneHome函数进行爆破
if (new String(j).startsWith(c)) {//如果以"Congratula"开头
flag2 = new String(j);
}
} catch (Exception e1) {
e1.printStackTrace();
}
Snackbar.make(v, flag2, 0).setAction("Action", (View.OnClickListener) null).show();
this.e = "";
}
}

/* access modifiers changed from: package-private */
public void a(String a2) throws Exception {
InputStream b2 = getAssets().open(a2);//打开"config.ini"
/*
<root>
key=IQCGt/+GXQYtMA==
rootkit=a/d/c/c
</root>
*/
ByteArrayOutputStream b22 = new ByteArrayOutputStream();
byte[] data = new byte[16384];
while (true) {
int nRead = b2.read(data, 0, data.length);
if (nRead == -1) {
break;
}
b22.write(data, 0, nRead);
}
b22.flush();
BufferedReader b4 = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(a(b22.toByteArray(), b))));
while (true) {
String c2 = b4.readLine();//逐行读取
if (c2 != null) {
if (c2.startsWith(g)) {//若以g开头,g="rootkit="
g = c2.substring(g.length());//g的值被更新,g="a/d/c/c"
}
if (c2.startsWith((String) f)) {//f="key="
f = Base64.decode(c2.substring(((String) f).length()), 0);//f的值被更新,f=b'!\x00\x86\xb7\xff\x86]\x06-0'
}
} else {
return;
}
}
}

/* JADX INFO: Multiple debug info for r1v1 java.lang.String: [D('a1' java.lang.String), D('a1' java.lang.StringBuilder)] */
static String a(String a2, int b2) {//b2恒等于1
StackTraceElement a0 = new Exception().getStackTrace()[b2];
StringBuilder a1 = new StringBuilder();
a1.append(a0.getClassName()).insert(b2, a0.getMethodName());
//a0.getClassName()=ctf.stratumauhhur.libdroid.a
//a0.getMethodName()=<clinit>
//a1=c<clinit>tf.stratumauhhur.libdroid.a
String a12 = a1.toString();
char[] a22 = new char[a2.length()];
char a4 = 0;
char a3 = (char) a12.length();
while (a4 < a2.length()) {
a22[a4] = (char) (a12.charAt(a3 - 1) ^ (a2.charAt(a4) ^ 18));
char a42 = (char) (a4 + 1);
if (a42 >= a2.length()) {
break;
}
a22[a42] = (char) (a12.charAt(a3 - 1) ^ (a2.charAt(a42) ^ 250));
a4 = (char) (a42 + 1);
a3 = (char) (a3 - 1);
if (a3 <= 0) {
a3 = (char) a12.length();
}
}
return String.valueOf(a22);
}

static {
System.loadLibrary("libdroid");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int __cdecl Java_ctf_stratumauhhur_libdroid_a_getOperatingSystem(int *a1)
{
int v1; // edx
__int16 v3; // [esp+1Ch] [ebp-20h]
__int16 v4; // [esp+1Eh] [ebp-1Eh]
__int16 v5; // [esp+20h] [ebp-1Ch]
__int16 v6; // [esp+22h] [ebp-1Ah]
__int16 v7; // [esp+24h] [ebp-18h]
__int16 v8; // [esp+26h] [ebp-16h]
__int16 v9; // [esp+28h] [ebp-14h]
__int16 v10; // [esp+2Ah] [ebp-12h]
__int16 v11; // [esp+2Ch] [ebp-10h]
__int16 v12; // [esp+2Eh] [ebp-Eh]

v3 = 0x10;
v4 = 0xF4;
v1 = *a1;
v5 = 0x52;
v6 = 0xB2;
v7 = 0x1F;
v8 = 0xF9;
v9 = 0x55;
v10 = 0xFA;
v11 = 0x13;
v12 = 0xFC;
return (*(v1 + 652))(a1, &v3, 10);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int __cdecl Java_ctf_stratumauhhur_libdroid_a_getPhoneNumber(int *a1)
{
int v1; // edx
__int16 v3; // [esp+18h] [ebp-24h]
__int16 v4; // [esp+1Ah] [ebp-22h]
__int16 v5; // [esp+1Ch] [ebp-20h]
__int16 v6; // [esp+1Eh] [ebp-1Eh]
__int16 v7; // [esp+20h] [ebp-1Ch]
__int16 v8; // [esp+22h] [ebp-1Ah]
__int16 v9; // [esp+24h] [ebp-18h]
__int16 v10; // [esp+26h] [ebp-16h]
__int16 v11; // [esp+28h] [ebp-14h]
__int16 v12; // [esp+2Ah] [ebp-12h]
__int16 v13; // [esp+2Ch] [ebp-10h]
__int16 v14; // [esp+2Eh] [ebp-Eh]

v3 = 0x11;
v4 = 0xF7;
v1 = *a1;
v5 = 0x5D;
v6 = 0xB6;
v7 = 0x1A;
v8 = 0xFF;
v9 = 0x19;
v10 = 0xFF;
v11 = 0x1C;
v12 = 0xF7;
v13 = 0xC;
v14 = 0xE9;
return (*(v1 + 652))(a1, &v3, 12);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int __cdecl Java_ctf_stratumauhhur_libdroid_a_generateConfusion(int *a1)
{
int v1; // edx
__int16 v3; // [esp+1Ah] [ebp-22h]
__int16 v4; // [esp+1Ch] [ebp-20h]
__int16 v5; // [esp+1Eh] [ebp-1Eh]
__int16 v6; // [esp+20h] [ebp-1Ch]
__int16 v7; // [esp+22h] [ebp-1Ah]
__int16 v8; // [esp+24h] [ebp-18h]
__int16 v9; // [esp+26h] [ebp-16h]
__int16 v10; // [esp+28h] [ebp-14h]
__int16 v11; // [esp+2Ah] [ebp-12h]
__int16 v12; // [esp+2Ch] [ebp-10h]
__int16 v13; // [esp+2Eh] [ebp-Eh]

v3 = 0x53;
v4 = 0xAA;
v1 = *a1;
v5 = 0xE;
v6 = 0xE7;
v7 = 0x42;
v8 = 0xAB;
v9 = 0x4D;
v10 = 0xA4;
v11 = 0x45;
v12 = 0xAC;
v13 = 0x50;
return (*(v1 + 652))(a1, &v3, 11);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
int __cdecl Java_ctf_stratumauhhur_libdroid_a_getFlag(int *a1)
{
int v1; // edx
__int16 v3; // [esp+1Ah] [ebp-42h]
__int16 v4; // [esp+1Ch] [ebp-40h]
__int16 v5; // [esp+1Eh] [ebp-3Eh]
__int16 v6; // [esp+20h] [ebp-3Ch]
__int16 v7; // [esp+22h] [ebp-3Ah]
__int16 v8; // [esp+24h] [ebp-38h]
__int16 v9; // [esp+26h] [ebp-36h]
__int16 v10; // [esp+28h] [ebp-34h]
__int16 v11; // [esp+2Ah] [ebp-32h]
__int16 v12; // [esp+2Ch] [ebp-30h]
__int16 v13; // [esp+2Eh] [ebp-2Eh]
__int16 v14; // [esp+30h] [ebp-2Ch]
__int16 v15; // [esp+32h] [ebp-2Ah]
__int16 v16; // [esp+34h] [ebp-28h]
__int16 v17; // [esp+36h] [ebp-26h]
__int16 v18; // [esp+38h] [ebp-24h]
__int16 v19; // [esp+3Ah] [ebp-22h]
__int16 v20; // [esp+3Ch] [ebp-20h]
__int16 v21; // [esp+3Eh] [ebp-1Eh]
__int16 v22; // [esp+40h] [ebp-1Ch]
__int16 v23; // [esp+42h] [ebp-1Ah]
__int16 v24; // [esp+44h] [ebp-18h]
__int16 v25; // [esp+46h] [ebp-16h]
__int16 v26; // [esp+48h] [ebp-14h]
__int16 v27; // [esp+4Ah] [ebp-12h]
__int16 v28; // [esp+4Ch] [ebp-10h]
__int16 v29; // [esp+4Eh] [ebp-Eh]

v3 = 0x20;
v4 = 0xF4;
v1 = *a1;
v5 = 0x4E;
v6 = 0xA6;
v7 = 0xF;
v8 = 0xBE;
v9 = 0x15;
v10 = 0xFC;
v11 = 0x5D;
v12 = 0xE7;
v13 = 0xF;
v14 = 0xE7;
v15 = 2;
v16 = 0xF5;
v17 = 0x19;
v18 = 0xEC;
v19 = 0x5B;
v20 = 0xF5;
v21 = 0x11;
v22 = 0xE4;
v23 = 0x1C;
v24 = 0xAD;
v25 = 0xF;
v26 = 0xFD;
v27 = 0x47;
v28 = 0xB5;
v29 = 0x52;
return (*(v1 + 652))(a1, &v3, 27);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int __cdecl Java_ctf_stratumauhhur_libdroid_a_installRootkit(int *a1)
{
int v1; // edx
__int16 v3; // [esp+1Ch] [ebp-20h]
__int16 v4; // [esp+1Eh] [ebp-1Eh]
__int16 v5; // [esp+20h] [ebp-1Ch]
__int16 v6; // [esp+22h] [ebp-1Ah]
__int16 v7; // [esp+24h] [ebp-18h]
__int16 v8; // [esp+26h] [ebp-16h]
__int16 v9; // [esp+28h] [ebp-14h]
__int16 v10; // [esp+2Ah] [ebp-12h]
__int16 v11; // [esp+2Ch] [ebp-10h]
__int16 v12; // [esp+2Eh] [ebp-Eh]

v3 = 0x30;
v4 = 0xF4;
v1 = *a1;
v5 = 0x52;
v6 = 0xB3;
v7 = 4;
v8 = 0xFF;
v9 = 0xF;
v10 = 0xE6;
v11 = 0x11;
v12 = 0xF4;
return (*(v1 + 652))(a1, &v3, 10);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl Java_ctf_stratumauhhur_libdroid_a_obtainWorldDomination(int *a1)
{
int v1; // edx
__int16 v3; // [esp+18h] [ebp-14h]
__int16 v4; // [esp+1Ah] [ebp-12h]
__int16 v5; // [esp+1Ch] [ebp-10h]
__int16 v6; // [esp+1Eh] [ebp-Eh]

v3 = 0x18;
v4 = 0xFE;
v1 = *a1;
v5 = 0x45;
v6 = 0xE9;
return (*(v1 + 652))(a1, &v3, 4);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int __cdecl Java_ctf_stratumauhhur_libdroid_a_installiOS(int *a1)
{
int v1; // edx
__int16 v3; // [esp+10h] [ebp-1Ch]
__int16 v4; // [esp+12h] [ebp-1Ah]
__int16 v5; // [esp+14h] [ebp-18h]
__int16 v6; // [esp+16h] [ebp-16h]
__int16 v7; // [esp+18h] [ebp-14h]
__int16 v8; // [esp+1Ah] [ebp-12h]
__int16 v9; // [esp+1Ch] [ebp-10h]
__int16 v10; // [esp+1Eh] [ebp-Eh]

v3 = 1;
v4 = 0xF4;
v1 = *a1;
v5 = 0x53;
v6 = 0xA0;
v7 = 0x1D;
v8 = 0xF7;
v9 = 0xF;
v10 = 0xAE;
return (*(v1 + 652))(a1, &v3, 8);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
int __cdecl Java_ctf_stratumauhhur_libdroid_a_phoneHome(int a1, int a2, int a3, int a4)
{
unsigned __int8 *v4; // esi
int v5; // ecx
int v6; // ebp
unsigned int v7; // esi
unsigned int v8; // edi
unsigned int v9; // ecx
int v10; // edi
int v12; // [esp+14h] [ebp-28h]
int v13; // [esp+18h] [ebp-24h]
int v14; // [esp+1Ch] [ebp-20h]
char *v15; // [esp+20h] [ebp-1Ch]
unsigned int v16; // [esp+24h] [ebp-18h]
int v17; // [esp+28h] [ebp-14h]
int v18; // [esp+2Ch] [ebp-10h]

v17 = (*(*a1 + 736))(a1, a3, 0); // FEA0AD802059AB12D7C39C88FA2C1DFC81460DDCE9CECC5778F5415F520236D53318663A4026E86EB6CD72B73C0166B14F9923639577346169F6A953403741434F98952C7A273C98681A88A8B785BB154F1A014DC9C89B7578577F980DD851A822B95E594D714F1A81A9BF0729EDFD83
v18 = (*(*a1 + 736))(a1, a4, 0); // b'!\x00\x86\xb7\xff\x86]\x06-0'+...6?
v4 = v18;
v5 = (*(*a1 + 684))(a1, a3);
v12 = (v4[2] << 16) | (v4[3] << 24) | *v4 | (v4[1] << 8);
v13 = (v4[6] << 16) | (v4[7] << 24) | v4[4] | (v4[5] << 8);
v14 = (v4[10] << 16) | (v4[11] << 24) | v4[8] | (v4[9] << 8);
v6 = (v4[15] << 24) | v4[12] | (v4[13] << 8) | (v4[14] << 16);
if ( v5 > 0 )
{
v15 = (v17 + 1);
v16 = v17 + ((v5 - 1) & 0xFFFFFFF8) + 9;
do
{
v7 = (*v15 << 8) | (v15[2] << 24) | *(v15 - 1) | (v15[1] << 16);
v8 = 0xD5B7DDE0;
v9 = (v15[4] << 8) | v15[3] | (v15[6] << 24) | (v15[5] << 16);
do
{
v9 -= (v7 + v8) ^ (16 * v7 + v14) ^ (v6 + (v7 >> 5));
v7 -= (v9 + v8) ^ (16 * v9 + v12) ^ (v13 + (v9 >> 5));
v8 += 0x21524111;
}
while ( v8 );
*(v15 - 1) = v7;
v10 = (v15 + 8);
*(v10 - 8) = BYTE1(v7);
*(v10 - 7) = BYTE2(v7);
*(v10 - 6) = HIBYTE(v7);
*(v10 - 5) = v9;
*(v10 - 3) = BYTE2(v9);
*(v10 - 2) = HIBYTE(v9);
v15 += 8;
}
while ( v10 != v16 );
}
(*(*a1 + 768))(a1, a3, v17, 0);
return (*(*a1 + 768))(a1, a4, v18, 0);
}

static String a(String a2, int b2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
a12="c<clinit>tf.stratumauhhur.libdroid.a"
a=[0x10,0xF4,0x52,0xB2,0x1F,0xF9,0x55,0xFA,0x13,0xFC]
b=[0x11,0xF7,0x5D,0xB6,0x1A,0xFF,0x19,0xFF,0x1C,0xF7,0x0C,0xE9]
c=[0x30,0xF4,0x52,0xB3,0x04,0xFF,0x0F,0xE6,0x11,0xF4]
d=[0x53,0xAA,0x0E,0xE7,0x42,0xAB,0x4D,0xA4,0x45,0xAC,0x50]
f=[0x18,0xFE,0x45,0xE9]
flag=[0x20,0xF4,0x4E,0xA6,0x0F,0xBE,0x15,0xFC,0x5D,0xE7,0x0F,0xE7,0x02,0xF5,0x19,0xEC,0x5B,0xF5,0x11,0xE4,0x1C,0xAD,0x0F,0xFD,0x47,0xB5,0x52]
file_name=[0x01,0xF4,0x53,0xA0,0x1D,0xF7,0x0F,0xAE]
a4=0
a3=len(a12)
a2=file_name
a22=[0 for i in range(len(a2))]
while a4<len(a2):
a22[a4]=ord(a12[a3-1])^(a2[a4]^18)
a42=a4+1
if a42>=len(a2):
break
a22[a42]=ord(a12[a3-1])^(a2[a42]^250)
a4=a42+1
a3-=1
if a3<=0:
a3=len(a12)
for i in a22:
print(chr(i),end="")
'''
a="config.ini"
b="blablablabla"
c="Congratula"
d=" 1234567890"
f="key="
flag="Sorry no rootkit for you :("
file_name="rootkit="
'''
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include<stdio.h>

void test(unsigned char arg1,unsigned char arg2,unsigned char arg3,unsigned char arg4,unsigned char arg5,unsigned char arg6){
unsigned char *v10;
unsigned char v17[113]={0xFE,0xA0,0xAD,0x80,0x20,0x59,0xAB,0x12,0xD7,0xC3,0x9C,0x88,0xFA,0x2C,0x1D,0xFC,0x81,0x46,0x0D,0xDC,0xE9,0xCE,0xCC,0x57,0x78,0xF5,0x41,0x5F,0x52,0x02,0x36,0xD5,0x33,0x18,0x66,0x3A,0x40,0x26,0xE8,0x6E,0xB6,0xCD,0x72,0xB7,0x3C,0x01,0x66,0xB1,0x4F,0x99,0x23,0x63,0x95,0x77,0x34,0x61,0x69,0xF6,0xA9,0x53,0x40,0x37,0x41,0x43,0x4F,0x98,0x95,0x2C,0x7A,0x27,0x3C,0x98,0x68,0x1A,0x88,0xA8,0xB7,0x85,0xBB,0x15,0x4F,0x1A,0x01,0x4D,0xC9,0xC8,0x9B,0x75,0x78,0x57,0x7F,0x98,0x0D,0xD8,0x51,0xA8,0x22,0xB9,0x5E,0x59,0x4D,0x71,0x4F,0x1A,0x81,0xA9,0xBF,0x07,0x29,0xED,0xFD,0x83};
unsigned char v18[16]={0x21,0x00,0x86,0xb7,0xff,0x86,0x5d,0x06,0x2d,0x30};
v18[10]=arg1;
v18[11]=arg2;
v18[12]=arg3;
v18[13]=arg4;
v18[14]=arg5;
v18[15]=arg6;
unsigned int v12 = (v18[2] << 16) | (v18[3] << 24) | *v18 | (v18[1] << 8);
unsigned int v13 = (v18[6] << 16) | (v18[7] << 24) | v18[4] | (v18[5] << 8);
unsigned int v14 = (v18[10] << 16) | (v18[11] << 24) | v18[8] | (v18[9] << 8);
unsigned int v6 = (v18[15] << 24) | v18[12] | (v18[13] << 8) | (v18[14] << 16);
int v5=112;
if(v5>0){
unsigned char *v15=v17+1;
unsigned char *v16 = v17 + ((v5 - 1) & 0xFFFFFFF8) + 9;
do{
unsigned int v7 = (*v15 << 8) | (v15[2] << 24) | *(v15 - 1) | (v15[1] << 16);
unsigned int v8 = 0xD5B7DDE0;
unsigned int v9 = (v15[4] << 8) | v15[3] | (v15[6] << 24) | (v15[5] << 16);
do{
v9 -= (v7 + v8) ^ (16 * v7 + v14) ^ (v6 + (v7 >> 5));
v7 -= (v9 + v8) ^ (16 * v9 + v12) ^ (v13 + (v9 >> 5));
v8 += 0x21524111;
}while(v8);
unsigned char v7_0,v7_1,v7_2,v7_3,v9_0,v9_1,v9_2,v9_3;
v7_0=v7&0xff;
v7_1=(v7>>8)&0xff;
v7_2=(v7>>16)&0xff;
v7_3=(v7>>24)&0xff;
v9_0=v9&0xff;
v9_1=(v9>>8)&0xff;
v9_2=(v9>>16)&0xff;
v9_3=(v9>>24)&0xff;
*(v15 - 1) = v7_0;
unsigned char *v10 = (v15 + 8);
*(v10 - 8) = v7_1;
*(v10 - 7) = v7_2;
*(v10 - 6) = v7_3;
*(v10 - 5) = v9_0;
*(v10 - 4) = v9_1;
*(v10 - 3) = v9_2;
*(v10 - 2) = v9_3;
v15 += 8;
}while(v10 != v16 && v15-v17<=112);
}
/*for(int i=0;i<112;++i){
printf("%c",v17[i]);
}
printf("\n");*/
if(v17[0]==67&&v17[1]==111&&v17[2]==110){//Con
printf("%c%c%c%c%c%c ",arg1,arg2,arg3,arg4,arg5,arg6);
for(int i=0;i<112;++i){
printf("%c",v17[i]);
}
printf("\n\n");
}
}
int main(){
unsigned char button[12]=" 1234567890";
for(int i=0;i<12;++i){
for(int j=0;j<12;++j){
for(int k=0;k<12;++k){
for(int l=0;l<12;++l){
for(int m=0;m<12;++m){
for(int n=0;n<12;++n){
test(button[i],button[j],button[k],button[l],button[m],button[n]);
}
}
}
}
}
}
return 0;
}
1
1 3875  Congratulations! The rootkit is sucessfully installed. The Flag is 32C3_this_is_build_for_flag_ship_phones

输入103875得到flag32C3_this_is_build_for_flag_ship_phones

2019_西湖论剑_预选赛

testre

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
void *ptr; // ST10_8
__int64 v5; // [rsp+18h] [rbp-28h]
char input; // [rsp+20h] [rbp-20h]
int v7; // [rsp+3Ch] [rbp-4h]

v7 = 0;
v5 = 256LL;
sub_400D00(&input, 17uLL);
ptr = malloc(256uLL);
sub_400700(ptr, &v5, &input, 16uLL);
free(ptr);
return 0LL;
}

读入函数

sub_400D00
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__int64 __fastcall sub_400D00(__int64 a1, unsigned __int64 a2)
{
char buf; // [rsp+17h] [rbp-19h]
unsigned __int64 i; // [rsp+18h] [rbp-18h]
unsigned __int64 v5; // [rsp+20h] [rbp-10h]
__int64 v6; // [rsp+28h] [rbp-8h]

v6 = a1;
v5 = a2;
for ( i = 0LL; i < v5; ++i ) // 长度为17
{
read(0, &buf, 1uLL);
*(v6 + i) = buf;
}
*(v6 + v5 - 1) = 0;
fflush(stdout);
return i;
}

输入长度为17,最后一位被去除,实际有效长度为16位

处理函数

sub_400700
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// a2=256,a4=16
__int64 __fastcall sub_400700(void *a1, _QWORD *a2, __int64 a3, size_t a4)
{
unsigned __int8 *v4; // rcx
__int64 v6; // [rsp+0h] [rbp-C0h]
int c; // [rsp+8h] [rbp-B8h]
char v8; // [rsp+Fh] [rbp-B1h]
int v9; // [rsp+10h] [rbp-B0h]
bool v10; // [rsp+17h] [rbp-A9h]
unsigned __int8 *v11; // [rsp+18h] [rbp-A8h]
char v12; // [rsp+27h] [rbp-99h]
int v13; // [rsp+28h] [rbp-98h]
int v14; // [rsp+2Ch] [rbp-94h]
unsigned __int64 i; // [rsp+30h] [rbp-90h]
size_t n_num_23; // [rsp+38h] [rbp-88h]
size_t v17; // [rsp+40h] [rbp-80h]
size_t v18; // [rsp+48h] [rbp-78h]
size_t j; // [rsp+50h] [rbp-70h]
size_t v20; // [rsp+58h] [rbp-68h]
int per_ch; // [rsp+64h] [rbp-5Ch]
unsigned __int64 temp; // [rsp+68h] [rbp-58h]
int v23_num_20; // [rsp+74h] [rbp-4Ch]
__int64 *v24; // [rsp+78h] [rbp-48h]
__int64 input; // [rsp+80h] [rbp-40h]
void *v26; // [rsp+88h] [rbp-38h]
int v27; // [rsp+94h] [rbp-2Ch]
unsigned __int64 len_16; // [rsp+98h] [rbp-28h]
__int64 v29; // [rsp+A0h] [rbp-20h]
_QWORD *v30; // [rsp+A8h] [rbp-18h]
void *result; // [rsp+B0h] [rbp-10h]
char v32; // [rsp+BFh] [rbp-1h]

result = a1;
v30 = a2;
v29 = a3;
len_16 = a4;
v27 = 0xDEADBEEF;
v26 = malloc(0x100uLL);
input = v29;
v24 = &v6;
temp = 0LL;
v17 = 0LL;
for ( i = 0LL; i < len_16; ++i ) // junk code
{
v13 = *(input + i);
*(v26 + i) = byte_400E90[i % 29] ^ v13;
*(v26 + i) += *(input + i);
}
while ( 1 ) // check0
{
v12 = 0;
if ( v17 < len_16 )
v12 = ~(*(input + v17) != 0);
if ( !(v12 & 1) ) // v12是偶数
break;
++v17;
}
n_num_23 = ((0x28F5C28F5C28F5C3LL * (138 * (len_16 - v17) >> 2) >> 64) >> 2) + 1;// 23
v23_num_20 = ((0xAAAAAAAAAAAAAAABLL * ((v17 + len_16) << 6) >> 64) >> 5) - 1;// 20
v11 = &v6 - ((((0x28F5C28F5C28F5C3LL * (138 * (len_16 - v17) >> 2) >> 64) >> 2) + 16) & 0xFFFFFFFFFFFFFFF0LL);
memset(v11, 0, n_num_23);
v20 = v17;
v18 = n_num_23 - 1;
while ( v20 < len_16 )
{
per_ch = *(input + v20);
for ( j = n_num_23 - 1; ; --j )
{
v10 = 1;
if ( j <= v18 )
v10 = per_ch != 0;
if ( !v10 )
break;
temp = v11[j] << 6;
per_ch += v11[j] << 8; // per_ch=per_ch+v11[j]*256
v9 = 64;
v11[j] = per_ch % 58; // base58???
*(v26 + j) = temp & 0x3F;
temp >>= 6;
per_ch /= 58;
v27 /= v9;
if ( !j )
break;
}
++v20;
v18 = j;
}
for ( j = 0LL; ; ++j ) // check0
{
v8 = 0;
if ( j < n_num_23 )
v8 = ~(v11[j] != 0);
if ( !(v8 & 1) )
break;
}
if ( *v30 > n_num_23 + v17 - j )
{
if ( v17 )
{
c = 61;
memset(result, 49, v17);
memset(v26, c, v17);
}
v20 = v17;
while ( j < n_num_23 )
{
v4 = v11;
*(result + v20) = byte_400EB0[v11[j]];
*(v26 + v20++) = byte_400EF0[v4[j++]];
}
*(result + v20) = 0;
*v30 = v20 + 1;
if ( !strncmp(result, "D9", 2uLL)
&& !strncmp(result + 20, "Mp", 2uLL)
&& !strncmp(result + 18, "MR", 2uLL)
&& !strncmp(result + 2, "cS9N", 4uLL)
&& !strncmp(result + 6, "9iHjM", 5uLL)
&& !strncmp(result + 11, "LTdA8YS", 7uLL) )// D9cS9N9iHjMLTdA8YSMRMp
// 可以对v11进行推导
{
HIDWORD(v6) = puts("correct!");
}
v32 = 1;
v14 = 1;
}
else
{
*v30 = n_num_23 + v17 - j + 1;
v32 = 0;
v14 = 1;
}
return v32 & 1;
}

从结果往前推导,便于提出混淆函数与变量

目标结果为D9cS9N9iHjMLTdA8YSMRMp,而resultv11有关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
while ( v20 < len_16 )
{
per_ch = *(input + v20);
for ( j = n_num_23 - 1; ; --j )
{
v10 = 1;
if ( j <= v18 )
v10 = per_ch != 0;
if ( !v10 )
break;
temp = v11[j] << 6;
per_ch += v11[j] << 8; // per_ch=per_ch+v11[j]*256
v9 = 64;
v11[j] = per_ch % 58; // base58???
*(v26 + j) = temp & 0x3F;
temp >>= 6;
per_ch /= 58;
v27 /= v9;
if ( !j )
break;
}
++v20;
v18 = j;
}
1
2
3
per_ch += v11[j] << 8;                    // per_ch=per_ch+v11[j]*256
v11[j] = per_ch % 58; // base58???
per_ch /= 58;

可以推断为base58

根据密文D9cS9N9iHjMLTdA8YSMRMp进行解密,得到flagbase58_is_boring

1
2
import base58
print(base58.b58decode(b"D9cS9N9iHjMLTdA8YSMRMp"))

2019_DDCTF

Windows_Reverse2

PEiD查壳(ASPack 2.12 -> Alexey Solodovnikov)

  • 手动脱壳

x32dbg载入,步进到call 6B600A得到ESP00F8FF00,在此处下断点

运行到断点处,然后步进到第二个ret,得到push ebp处的地址进行dump

dump后进行查壳

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int maybe_main()
{
char v1; // [esp+8h] [ebp-C04h]
char v2; // [esp+9h] [ebp-C03h]
char input; // [esp+408h] [ebp-804h]
char v4; // [esp+409h] [ebp-803h]
char v5; // [esp+808h] [ebp-404h]
char v6; // [esp+809h] [ebp-403h]

input = 0;
memset(&v4, 0, 1023); // memset
v5 = 0;
memset(&v6, 0, 1023); // memset
MEMORY[0x712420C1]("input code:");
MEMORY[0x712426D4]("%s", &input);
if ( !sub_6D11F0(&input) ) // 输入必须为0~9,A~F中
{
MEMORY[0x712420C1]("invalid input\n");
MEMORY[0x71232455](0);
}
sub_6D1240(&input, &v5);
v1 = 0;
memset(&v2, 0, 1023); // memset
MEMORY[0x71242E73](&v1, "DDCTF{%s}", &v5);
if ( !strcmp(&v1, "DDCTF{reverse+}") )
MEMORY[0x712420C1]("You've got it !!! %s\n", &v1);
else
MEMORY[0x712420C1]("Something wrong. Try again...\n");
return 0;
}

sub_6D1240(&input, &v5);对输入进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int __usercall sub_6D1240@<eax>(const char *input@<esi>, int a2)
{
signed int input_len; // edi
signed int index; // edx
char v4; // bl
char each; // al
char each_1; // al
unsigned int v7; // ecx
char v9; // [esp+Bh] [ebp-405h]
char v10; // [esp+Ch] [ebp-404h]
char v11; // [esp+Dh] [ebp-403h]

input_len = strlen(input);
v10 = 0;
memset(&v11, 0, 1023);
index = 0;
if ( input_len > 0 )
{
v4 = v9;
do
{
each = input[index];
if ( (input[index] - 48) > 9u ) // A~F转换为10~15
{
if ( (each - 65) <= 5u )
v9 = each - 55;
}
else
{
v9 = input[index] - 48; // 0~9
}
each_1 = input[index + 1];
if ( (input[index + 1] - 48) > 9u )
{
if ( (each_1 - 65) <= 5u )
v4 = each_1 - 55;
}
else
{
v4 = input[index + 1] - 48;
}
v7 = index >> 1;
index += 2;
*(&v10 + v7) = v4 | 16 * v9;
}
while ( index < input_len );
}
return sub_6D1000(input_len / 2, a2);
}

sub_6D1000(input_len / 2, a2);真正的处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
int __cdecl sub_6D1000(int a1, int a2)
{
char *v2; // ecx
int v3; // ebp
char *v4; // edi
signed int v5; // esi
unsigned __int8 v6; // bl
signed int v7; // esi
int v8; // edi
int v9; // edi
int v10; // esi
int v11; // edi
int *v12; // eax
unsigned __int8 v14; // [esp+14h] [ebp-38h]
unsigned __int8 v15; // [esp+15h] [ebp-37h]
unsigned __int8 v16; // [esp+16h] [ebp-36h]
int v17; // [esp+18h] [ebp-34h]
int v18; // [esp+1Ch] [ebp-30h]
char v19; // [esp+20h] [ebp-2Ch]
int *v20; // [esp+24h] [ebp-28h]
int v21; // [esp+34h] [ebp-18h]
unsigned int v22; // [esp+38h] [ebp-14h]
int v23; // [esp+48h] [ebp-4h]

v3 = a1;
v4 = v2; // string: reverse+
v18 = a2;
MEMORY[0x74A15E81](&v19); // allocator
v5 = 0;
v23 = 0;
if ( a1 )
{
do
{
*(&v14 + v5) = *v4;
v6 = v15;
++v5;
--v3;
++v4;
if ( v5 == 3 )
{ // base64
LOBYTE(v17) = v14 >> 2;
BYTE1(v17) = (v15 >> 4) + 16 * (v14 & 3);
BYTE2(v17) = (v16 >> 6) + 4 * (v15 & 0xF);
HIBYTE(v17) = v16 & 0x3F;
v7 = 0;
do
MEMORY[0x74A172EE](&v19, (byte_6D3020[*(&v17 + v7++)] ^ 0x76));// allocator
// base64改表+异或
while ( v7 < 4 );
v5 = 0;
}
}
while ( v3 );
if ( v5 )
{
if ( v5 < 3 )
{
memset((&v14 + v5), 0, 3 - v5);
v6 = v15;
}
BYTE1(v17) = (v6 >> 4) + 16 * (v14 & 3);
LOBYTE(v17) = v14 >> 2;
BYTE2(v17) = (v16 >> 6) + 4 * (v6 & 0xF);
v8 = 0;
for ( HIBYTE(v17) = v16 & 0x3F; v8 < v5 + 1; ++v8 )
MEMORY[0x74A172EE](&v19, (byte_6D3020[*(&v17 + v8)] ^ 0x76));
if ( v5 < 3 )
{
v9 = 3 - v5;
do
{
MEMORY[0x74A172EE](&v19, '=');
--v9;
}
while ( v9 );
}
}
}
v10 = v21;
v11 = v18;
memset(v18, 0, v21 + 1);
v12 = v20;
if ( v22 < 0x10 )
v12 = &v20;
sub_6D1C64(v11, v12, v10); // memcpy
v23 = -1;
return MEMORY[0x74A15EBB]();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
base64_table=[55, 52, 53, 50, 51, 48, 49, 62, 63, 60, 61, 58, 59, 56, 57, 38, 39, 36, 37, 34, 35, 32, 33, 46, 47, 44, 23, 20, 21, 18, 19, 16, 17, 30, 31, 28, 29, 26, 27, 24, 25, 6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 70, 71, 68, 69, 66, 67, 64, 65, 78, 79, 93, 89]
s="reverse+"
s_list=[4, 19, 0, 19, 4, 5, 19, 93]#s^0x76
s_posi=[43, 30, 47, 30, 43, 44, 30, 62]#s_list在base64改表中的对应位置
for i in s_posi:
print(bin(i)[2:].zfill(8))

'''
00101011
00011110
00101111
00011110
00101011
00101100
00011110
00111110

hex(0b10101101) ad
hex(0b11101011) eb
hex(0b11011110) de

hex(0b10101110) ae
hex(0b11000111) c7
hex(0b10111110) be

flag:DDCTF{ADEBDEAEC7BE}
'''
  • 工具脱壳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int __cdecl main(int argc, const char **argv, const char **envp)
{
char Dest; // [esp+8h] [ebp-C04h]
char v5; // [esp+9h] [ebp-C03h]
char v6; // [esp+408h] [ebp-804h]
char Dst; // [esp+409h] [ebp-803h]
char v8; // [esp+808h] [ebp-404h]
char v9; // [esp+809h] [ebp-403h]

v6 = 0;
memset(&Dst, 0, 0x3FFu);
v8 = 0;
memset(&v9, 0, 0x3FFu);
printf(Format);
scanf(aS, &v6);
if ( !(unsigned __int8)sub_7411F0() )
{
printf(aInvalidInput);
exit(0);
}
sub_741240(&v8);
Dest = 0;
memset(&v5, 0, 0x3FFu);
sprintf(&Dest, aDdctfS, &v8);
if ( !strcmp(&Dest, aDdctfReverse) )
printf(aYouVeGotItS, &Dest);
else
printf(aSomethingWrong);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int __usercall sub_741240@<eax>(const char *a1@<esi>, int a2)
{
signed int v2; // edi
signed int v3; // edx
char v4; // bl
char v5; // al
char v6; // al
unsigned int v7; // ecx
char v9; // [esp+Bh] [ebp-405h]
char v10; // [esp+Ch] [ebp-404h]
char Dst; // [esp+Dh] [ebp-403h]

v2 = strlen(a1);
v10 = 0;
memset(&Dst, 0, 0x3FFu);
v3 = 0;
if ( v2 > 0 )
{
v4 = v9;
do
{
v5 = a1[v3];
if ( (unsigned __int8)(a1[v3] - 48) > 9u )
{
if ( (unsigned __int8)(v5 - 65) <= 5u )
v9 = v5 - 55;
}
else
{
v9 = a1[v3] - 48;
}
v6 = a1[v3 + 1];
if ( (unsigned __int8)(a1[v3 + 1] - 48) > 9u )
{
if ( (unsigned __int8)(v6 - 65) <= 5u )
v4 = v6 - 55;
}
else
{
v4 = a1[v3 + 1] - 48;
}
v7 = (unsigned int)v3 >> 1;
v3 += 2;
*(&v10 + v7) = v4 | 16 * v9;
}
while ( v3 < v2 );
}
return sub_741000(v2 / 2, a2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
int __cdecl sub_741000(int a1, void *a2)
{
char *v2; // ecx
int v3; // ebp
char *v4; // edi
signed int v5; // esi
unsigned __int8 v6; // bl
signed int v7; // esi
int v8; // edi
int v9; // edi
size_t v10; // esi
void *v11; // edi
const void *v12; // eax
unsigned __int8 Dst; // [esp+14h] [ebp-38h]
unsigned __int8 v15; // [esp+15h] [ebp-37h]
unsigned __int8 v16; // [esp+16h] [ebp-36h]
char v17; // [esp+18h] [ebp-34h]
char v18; // [esp+19h] [ebp-33h]
char v19; // [esp+1Ah] [ebp-32h]
char i; // [esp+1Bh] [ebp-31h]
void *v21; // [esp+1Ch] [ebp-30h]
char v22; // [esp+20h] [ebp-2Ch]
void *Src; // [esp+24h] [ebp-28h]
size_t Size; // [esp+34h] [ebp-18h]
unsigned int v25; // [esp+38h] [ebp-14h]
int v26; // [esp+48h] [ebp-4h]

v3 = a1;
v4 = v2;
v21 = a2;
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<char,std::char_traits<char>,std::allocator<char>>(&v22);
v5 = 0;
v26 = 0;
if ( a1 )
{
do
{
*(&Dst + v5) = *v4;
v6 = v15;
++v5;
--v3;
++v4;
if ( v5 == 3 )
{
v17 = Dst >> 2;
v18 = (v15 >> 4) + 16 * (Dst & 3);
v19 = (v16 >> 6) + 4 * (v15 & 0xF);
i = v16 & 0x3F;
v7 = 0;
do
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(
&v22,
(unsigned __int8)(byte_743020[(unsigned __int8)*(&v17 + v7++)] ^ 0x76));
while ( v7 < 4 );
v5 = 0;
}
}
while ( v3 );
if ( v5 )
{
if ( v5 < 3 )
{
memset(&Dst + v5, 0, 3 - v5);
v6 = v15;
}
v18 = (v6 >> 4) + 16 * (Dst & 3);
v17 = Dst >> 2;
v19 = (v16 >> 6) + 4 * (v6 & 0xF);
v8 = 0;
for ( i = v16 & 0x3F; v8 < v5 + 1; ++v8 )
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(
&v22,
(unsigned __int8)(byte_743020[(unsigned __int8)*(&v17 + v8)] ^ 0x76));
if ( v5 < 3 )
{
v9 = 3 - v5;
do
{
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(&v22, 61);
--v9;
}
while ( v9 );
}
}
}
v10 = Size;
v11 = v21;
memset(v21, 0, Size + 1);
v12 = Src;
if ( v25 < 0x10 )
v12 = &Src;
memcpy(v11, v12, v10);
v26 = -1;
return std::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string<char,std::char_traits<char>,std::allocator<char>>();
}

2019嘉韦思杯

梅津美治郎

进行动态调试

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
int __cdecl main(int argc, const char **argv, const char **envp)
{
const CHAR *v3; // ebx
HMODULE v4; // eax
void (__stdcall *v5)(HMODULE, LPCSTR); // eax
char v7; // [esp+1h] [ebp-157h]
char v8[4]; // [esp+15h] [ebp-143h]
int v9; // [esp+20h] [ebp-138h]
int v10; // [esp+26h] [ebp-132h]
int v11; // [esp+2Ah] [ebp-12Eh]
int v12; // [esp+2Eh] [ebp-12Ah]
int v13; // [esp+32h] [ebp-126h]
int v14; // [esp+36h] [ebp-122h]
int v15; // [esp+3Ah] [ebp-11Eh]
__int16 v16; // [esp+3Eh] [ebp-11Ah]
int v17; // [esp+40h] [ebp-118h]
int v18; // [esp+44h] [ebp-114h]
int v19; // [esp+48h] [ebp-110h]
int v20; // [esp+4Ch] [ebp-10Ch]
int v21; // [esp+50h] [ebp-108h]
int v22; // [esp+54h] [ebp-104h]
int v23; // [esp+58h] [ebp-100h]
int v24; // [esp+5Ch] [ebp-FCh]
int v25; // [esp+60h] [ebp-F8h]
int v26; // [esp+64h] [ebp-F4h]
int v27; // [esp+68h] [ebp-F0h]
int v28; // [esp+6Ch] [ebp-ECh]
int v29; // [esp+70h] [ebp-E8h]
char v30; // [esp+74h] [ebp-E4h]
int v31; // [esp+75h] [ebp-E3h]
int v32; // [esp+79h] [ebp-DFh]
int v33; // [esp+7Dh] [ebp-DBh]
int v34; // [esp+81h] [ebp-D7h]
int v35; // [esp+85h] [ebp-D3h]
int v36; // [esp+89h] [ebp-CFh]
int v37; // [esp+8Dh] [ebp-CBh]
int v38; // [esp+91h] [ebp-C7h]
__int16 v39; // [esp+95h] [ebp-C3h]
int v40; // [esp+97h] [ebp-C1h]
int v41; // [esp+9Bh] [ebp-BDh]
int v42; // [esp+9Fh] [ebp-B9h]
int v43; // [esp+A3h] [ebp-B5h]
int v44; // [esp+A7h] [ebp-B1h]
int v45; // [esp+ABh] [ebp-ADh]
int v46; // [esp+AFh] [ebp-A9h]
int v47; // [esp+B3h] [ebp-A5h]
char v48; // [esp+B7h] [ebp-A1h]
int v49; // [esp+B8h] [ebp-A0h]
int v50; // [esp+BEh] [ebp-9Ah]
int v51; // [esp+C2h] [ebp-96h]
int v52; // [esp+C6h] [ebp-92h]
int v53; // [esp+CAh] [ebp-8Eh]
int v54; // [esp+CEh] [ebp-8Ah]
int v55; // [esp+D2h] [ebp-86h]
int v56; // [esp+D6h] [ebp-82h]
int v57; // [esp+DAh] [ebp-7Eh]
char v58; // [esp+DEh] [ebp-7Ah]
int v59; // [esp+DFh] [ebp-79h]
int v60; // [esp+E3h] [ebp-75h]
int v61; // [esp+E7h] [ebp-71h]
int v62; // [esp+EBh] [ebp-6Dh]
int v63; // [esp+EFh] [ebp-69h]
int v64; // [esp+F3h] [ebp-65h]
int v65; // [esp+F7h] [ebp-61h]
int v66; // [esp+FBh] [ebp-5Dh]
__int16 v67; // [esp+FFh] [ebp-59h]
int v68; // [esp+101h] [ebp-57h]
int v69; // [esp+105h] [ebp-53h]
char v70; // [esp+109h] [ebp-4Fh]
int v71; // [esp+10Ah] [ebp-4Eh]
int v72; // [esp+10Eh] [ebp-4Ah]
int v73; // [esp+112h] [ebp-46h]
int v74; // [esp+116h] [ebp-42h]
int v75; // [esp+11Ah] [ebp-3Eh]
int v76; // [esp+11Eh] [ebp-3Ah]
int v77; // [esp+122h] [ebp-36h]
int v78; // [esp+126h] [ebp-32h]
int v79; // [esp+12Ah] [ebp-2Eh]
int v80; // [esp+12Eh] [ebp-2Ah]
int v81; // [esp+132h] [ebp-26h]
int v82; // [esp+136h] [ebp-22h]
int v83; // [esp+13Ah] [ebp-1Eh]
int v84; // [esp+13Eh] [ebp-1Ah]
int v85; // [esp+142h] [ebp-16h]
int v86; // [esp+146h] [ebp-12h]
int v87; // [esp+14Ah] [ebp-Eh]
__int16 v88; // [esp+14Eh] [ebp-Ah]
int *v89; // [esp+150h] [ebp-8h]

v89 = &argc;
sub_402940();
puts(
" . \n"
" _|_ ROBOTIC AUTHENTICATION SYSTEM\n"
" /\\/\\ (. .) /\n"
" `||' |#| \n"
" ||__.-\"-\"-.___ \n"
" `---| . . |--.\\ \n"
" | : : | ,||,\n"
" `..-..' \\/\\/\n"
" || || \n"
" || || \n"
" |__|__| \n");
v49 = 1337;
v50 = 1617194321;
v51 = 1679910002;
v52 = 1935963503;
v53 = 1684632865;
v54 = 1936221985;
v55 = 1361147250;
v56 = 1987211872;
v57 = 996504430;
v58 = 1;
v40 = 1617194321;
v41 = 1679910002;
v42 = 1935963503;
v43 = 1684632865;
v44 = 1936221985;
v45 = 1361147250;
v46 = 1987211872;
v47 = 996504430;
v48 = 1;
v59 = 1617194321;
v60 = 1679910002;
v61 = 1935963503;
v62 = 1684632865;
v63 = 1650749985;
v64 = 560295790;
v65 = 1920098385;
v66 = 1702063734;
v67 = 315;
v31 = 1617194321;
v32 = 1679910002;
v33 = 1935963503;
v34 = 1684632865;
v35 = 1650749985;
v36 = 560295790;
v37 = 1920098385;
v38 = 1702063734;
v39 = 315;
v68 = 1869557876;
v69 = 1718432615;
v70 = 3;
v28 = 1869557876;
v29 = 1718432615;
v30 = 3;
v71 = 1869833322;
v72 = 858942820;
v73 = 1835885871;
v74 = 20906241;
v24 = 1869833322;
v25 = 858942820;
v26 = 1835885871;
v27 = 20906241;
v75 = 1466262848;
v76 = 1853186660;
v77 = 1147495539;
v78 = 1902404217;
v79 = 1869506677;
v80 = 1701797961;
v81 = 24339565;
v17 = 1466262848;
v18 = 1853186660;
v19 = 1147495539;
v20 = 1902404217;
v21 = 1869506677;
v22 = 1701797961;
v23 = 24339565;
v82 = 561278552;
v83 = 795830390;
v84 = 1869496865;
v85 = 1969255270;
v86 = 1969253748;
v87 = 1919905384;
v88 = 288;
v10 = 561278552;
v11 = 795830390;
v12 = 1869496865;
v13 = 1969255270;
v14 = 1969253748;
v15 = 1919905384;
v16 = 288;
v9 = 1337;
strcpy(v8, "r0b0RUlez!");
dword_40AD94 = (int)&v9;
dword_40ADA0 = (int)&v49;
plz_enter_first_pwd = (char *)&v40;
plz_enter_second_pwd = (char *)&v31;
dword_40AD98 = (int)&v28;
lpProcName = (LPCSTR)&v17;
lpModuleName = (LPCSTR)&v24;
dword_40ADA4 = (char *)&v10;
sub_401500(0);
v3 = lpProcName;
v4 = GetModuleHandleA(lpModuleName); // kernel32.dll
v5 = (void (__stdcall *)(HMODULE, LPCSTR))GetProcAddress(v4, v3);// AddVectoredExceptionHandler
v5((HMODULE)1, (LPCSTR)sub_40157F);
puts(plz_enter_first_pwd);
scanf("%20s", &v7);
if ( !strcmp(&v7, v8) )
{
puts("You passed level1!");
sub_4015EA(0);
}
return 0;
}

v8被赋值为r0b0RUlez!

sub_401500用于对lpProcName等字符串进行变换,变换完成后lpProcNameAddVectoredExceptionHandler(功能是在异常前执行指定函数),lpModuleNamekernel32.dll

第一个密码输入r0b0RUlez!,可以进入第二关

1
2
3
4
5
6
7
8
9
int __cdecl sub_4015EA(signed int a1)
{
if ( a1 <= 9 )
return sub_4015EA(a1 + 1);
puts(plz_enter_second_pwd);
dword_40ADA8 = 4199961;
__debugbreak();
return 0;
}

查看汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.text:00401607 loc_401607:                             ; CODE XREF: sub_4015EA+A↑j
.text:00401607 mov eax, ds:plz_enter_second_pwd
.text:0040160C mov [esp], eax ; char *
.text:0040160F call puts
.text:00401614 call $+5
.text:00401619 pop eax
.text:0040161A mov ds:dword_40ADA8, eax
.text:0040161F int 3 ; Trap to Debugger
.text:00401620 mov eax, 0
.text:00401625
.text:00401625 locret_401625: ; CODE XREF: sub_4015EA+1B↑j
.text:00401625 leave
.text:00401626 retn
.text:00401626 sub_4015EA endp

注意

1
2
.text:00401614 call    $+5
.text:00401619 pop eax

call $+5(从当前开始向下五个字节处开始执行)也就是跳转到pop eax,看起来和直接跳到下一条指令没什么区别

但实际上,call会把下一条要执行的指令地址压栈,这里也就是把00401619压栈,再pop eax,这时eax就是00401619

1
.text:0040161F int     3   

有一个int 3的异常,可以被AddVectoredExceptionHandler捕捉,由v5((HMODULE)1, (LPCSTR)sub_40157F);进入sub_40157F

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void __cdecl __noreturn sub_40157F(int a1)
{
char v1; // [esp+18h] [ebp-20h]
int v2; // [esp+2Ch] [ebp-Ch]

v2 = *(_DWORD *)(*(_DWORD *)(a1 + 4) + 184);
if ( v2 == dword_40ADA8 + 6 )
{
scanf("%20s", &v1);
if ( !sub_401547(&v1, (_BYTE *)dword_40AD98) )
puts(dword_40ADA4);
}
ExitProcess(0);
}
1
2
3
4
5
6
7
8
9
10
11
signed int __cdecl sub_401547(_BYTE *a1, _BYTE *a2)
{
while ( *a2 != 2 )
{
if ( *a1 != (*a2 ^ 2) )
return 1;
++a1;
++a2;
}
return 0;
}

dword_40AD98[117, 49, 110, 110, 102, 50, 108, 103]

由此可得第二关的密码

1
2
3
dword_40AD98=[117, 49, 110, 110, 102, 50, 108, 103]
for i in dword_40AD98:
print(chr(i^2),end="")

w3lld0ne

flag为flag{r0b0RUlez!_w3lld0ne}

9447 CTF 2014

no-strings-attached

可知这是32位的ELF程序,尝试运行

出现了无法运行的情况,安装gcc-multilib

sudo apt-get install gcc-multilib

  • 静态方法
main
1
2
3
4
5
6
7
8
int __cdecl main(int argc, const char **argv, const char **envp)
{
setlocale(6, &locale);
banner();
prompt_authentication();
authenticate();
return 0;
}
banner
1
2
3
4
5
6
7
8
9
10
int banner()
{
unsigned int v0; // eax

v0 = time(0);
srand(v0);
wprintf(&unk_80488B0);//运行时的第一句话
rand();
return wprintf(&unk_8048960);//运行时的第二句话
}
prompt_authentication
1
2
3
4
int prompt_authentication()
{
return wprintf(&unk_80489F8);//提示进行信息输入
}

authenticate中,将sdword_8048A90传递给了decrypt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void authenticate()
{
wchar_t ws[8192]; // [esp+1Ch] [ebp-800Ch]
wchar_t *s2; // [esp+801Ch] [ebp-Ch]

s2 = (wchar_t *)decrypt(&s, &dword_8048A90);
if ( fgetws(ws, 0x2000, stdin) )
{
ws[wcslen(ws) - 1] = 0;
if ( !wcscmp(ws, s2) )
wprintf(&unk_8048B44);
else
wprintf(&unk_8048BA4);
}
free(s2);
}
decrypt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
wchar_t *__cdecl decrypt(wchar_t *s, wchar_t *a2)
{
size_t v2; // eax
signed int v4; // [esp+1Ch] [ebp-1Ch]
signed int i; // [esp+20h] [ebp-18h]
signed int v6; // [esp+24h] [ebp-14h]
signed int v7; // [esp+28h] [ebp-10h]
wchar_t *dest; // [esp+2Ch] [ebp-Ch]

v6 = wcslen(s);
v7 = wcslen(a2);
v2 = wcslen(s);
dest = (wchar_t *)malloc(v2 + 1);
wcscpy(dest, s);
while ( v4 < v6 )
{
for ( i = 0; i < v7 && v4 < v6; ++i )//两字符串不断相减,到达尽头后回到起点继续相减,减出来的结果就是flag
dest[v4++] -= a2[i];
}
return dest;
}

sdword_8048A90

选中数据,用shift+E提取数据,选择C xxx (dec)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
s=[
58, 20, 0, 0, 54, 20, 0, 0, 55, 20,
0, 0, 59, 20, 0, 0, 128, 20, 0, 0,
122, 20, 0, 0, 113, 20, 0, 0, 120, 20,
0, 0, 99, 20, 0, 0, 102, 20, 0, 0,
115, 20, 0, 0, 103, 20, 0, 0, 98, 20,
0, 0, 101, 20, 0, 0, 115, 20, 0, 0,
96, 20, 0, 0, 107, 20, 0, 0, 113, 20,
0, 0, 120, 20, 0, 0, 106, 20, 0, 0,
115, 20, 0, 0, 112, 20, 0, 0, 100, 20,
0, 0, 120, 20, 0, 0, 110, 20, 0, 0,
112, 20, 0, 0, 112, 20, 0, 0, 100, 20,
0, 0, 112, 20, 0, 0, 100, 20, 0, 0,
110, 20, 0, 0, 123, 20, 0, 0, 118, 20,
0, 0, 120, 20, 0, 0, 106, 20, 0, 0,
115, 20, 0, 0, 123, 20, 0, 0, 128, 20,
0, 0
]
a2=[
1, 20, 0, 0, 2, 20, 0, 0, 3, 20,
0, 0, 4, 20, 0, 0, 5, 20, 0, 0
]
#去除最后多出来的4个零(字符串末尾的'\0')
len_s = len(s)
print(s,a2)
len_a2 = len(a2)
v2 = len(s)
out=[]
v4=0
while v4 < len_s:
for i in range(len_a2):
if v4<len_s:
out.append(s[v4]-a2[i])
v4+=1
print(out)
for i in out:
if i>=0:
print(chr(i),end="")

flag:9447{you_are_an_international_mystery}

  • 动态方法

由IDA分析知,在decrypt函数运行结束时会返回flag,在decrypt函数结束的地方0x08048707下断点,并查看寄存器中的内容

在IDA中查看authenticate的汇编

1
2
call    decrypt
mov [ebp+s2], eax

因此flag暂时位于寄存器eax中

也可以把断点打在decrypt函数,然后执行下一步操作

西湖论剑

easycpp

首先进行静态分析

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3; // r14
char v4; // r15
__int64 v5; // rdx
__int64 v6; // rdx
__int64 v7; // rdx
__int64 v8; // rdx
__int64 input_vector_temp_back_inserter; // r12
__int64 input_vector_end; // rbx
__int64 input_vector[1]; // rax
__int64 v12; // rdx
__int64 input_vector_temp_end; // rbx
__int64 input_vector_temp_begin; // rax
__int64 v15; // r8
__int64 v16; // r9
__int64 flag_end; // r12
__int64 input_vector_end_1; // rbx
__int64 input_vector_begin_1; // rax
__int64 v20; // rcx
__int64 v21; // r8
__int64 v22; // r9
unsigned int *v23; // rax
const char **v25; // [rsp+0h] [rbp-190h]
signed int i; // [rsp+1Ch] [rbp-174h]
signed int j; // [rsp+20h] [rbp-170h]
char fib_vector; // [rsp+30h] [rbp-160h]
char input_vector; // [rsp+50h] [rbp-140h]
char input_vector_temp; // [rsp+70h] [rbp-120h]
char input_vector_; // [rsp+90h] [rbp-100h]
char flag; // [rsp+B0h] [rbp-E0h]
__int64 v33; // [rsp+D0h] [rbp-C0h]
__int64 input_vector_begin; // [rsp+F0h] [rbp-A0h]
char input_array[72]; // [rsp+110h] [rbp-80h]
unsigned __int64 v36; // [rsp+158h] [rbp-38h]

v25 = argv;
v36 = __readfsqword(0x28u);
std::vector<int,std::allocator<int>>::vector(&fib_vector, argv, envp);
std::vector<int,std::allocator<int>>::vector(&input_vector, argv, v5);
std::vector<int,std::allocator<int>>::vector(&input_vector_temp, argv, v6);
std::vector<int,std::allocator<int>>::vector(&input_vector_, argv, v7);
std::vector<int,std::allocator<int>>::vector(&flag, argv, v8);
for ( i = 0; i <= 15; ++i )
{
scanf("%d", &input_array[4 * i], v25);
std::vector<int,std::allocator<int>>::push_back(&input_vector, &input_array[4 * i]);
}
for ( j = 0; j <= 15; ++j )
{
LODWORD(input_vector_begin) = fib(j); // 斐波那契数列
std::vector<int,std::allocator<int>>::push_back(&fib_vector, &input_vector_begin);
}
std::vector<int,std::allocator<int>>::push_back(&input_vector_temp, input_array);
input_vector_temp_back_inserter = std::back_inserter<std::vector<int,std::allocator<int>>>(&input_vector_temp);
input_vector_end = std::vector<int,std::allocator<int>>::end(&input_vector);
input_vector_begin = std::vector<int,std::allocator<int>>::begin(&input_vector);
input_vector[1] = __gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator+(
&input_vector_begin,
1LL);
std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::back_insert_iterator<std::vector<int,std::allocator<int>>>,main::{lambda(int)#1}>(
input_vector[1],
input_vector_end,
input_vector_temp_back_inserter,
(__int64)input_array); // input_vector_temp[0]=input_vector[0]+input_vector[1]
// input_vector_temp[1]=input_vector[0]+input_vector[2]
// input_vector_temp[2]=input_vector[0]+input_vector[3]
// ...
std::vector<int,std::allocator<int>>::vector(&v33, input_vector_end, v12);
input_vector_temp_end = std::vector<int,std::allocator<int>>::end(&input_vector_temp);
input_vector_temp_begin = std::vector<int,std::allocator<int>>::begin(&input_vector_temp);
std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::vector<int,std::allocator<int>>,main::{lambda(std::vector<int,std::allocator<int>>,int)#2}>(
(__int64)&input_vector_begin,
input_vector_temp_begin,
input_vector_temp_end,
(__int64)&v33,
v15,
v16,
v4);
std::vector<int,std::allocator<int>>::operator=(&input_vector_, &input_vector_begin);
std::vector<int,std::allocator<int>>::~vector(&input_vector_begin);
std::vector<int,std::allocator<int>>::~vector(&v33);
if ( (unsigned __int8)std::operator!=<int,std::allocator<int>>(&input_vector_, &fib_vector) )// 转换后的input_vector与斐波那契数列相同
{
puts("You failed!");
exit(0);
}
flag_end = std::back_inserter<std::vector<int,std::allocator<int>>>(&flag);
input_vector_end_1 = std::vector<int,std::allocator<int>>::end(&input_vector);
input_vector_begin_1 = std::vector<int,std::allocator<int>>::begin(&input_vector);
std::copy_if<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::back_insert_iterator<std::vector<int,std::allocator<int>>>,main::{lambda(int)#3}>(// 将input_vector中的奇数填入flag中
input_vector_begin_1,
input_vector_end_1,
flag_end,
v20,
v21,
v22,
v3);
puts("You win!");
printf("Your flag is:flag{", input_vector_end_1, v25);
v33 = std::vector<int,std::allocator<int>>::begin(&flag);
input_vector_begin = std::vector<int,std::allocator<int>>::end(&flag);// 变量复用,无影响
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int,std::allocator<int>>>(&v33, &input_vector_begin) )
{
v23 = (unsigned int *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*(&v33);
std::ostream::operator<<(&std::cout, *v23);
__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator++(&v33);
}
putchar('}');
std::vector<int,std::allocator<int>>::~vector(&flag);
std::vector<int,std::allocator<int>>::~vector(&input_vector_);
std::vector<int,std::allocator<int>>::~vector(&input_vector_temp);
std::vector<int,std::allocator<int>>::~vector(&input_vector);
std::vector<int,std::allocator<int>>::~vector(&fib_vector);
return 0;
}

main函数的主要逻辑为

  1. 读入16个数字,将其写入到input_vector

  2. 将斐波那契数列的前16项写入到fib_vector

  3. std::transform逻辑:

    input_vector_temp[0]=input_vector[0]+input_vector[1]

    input_vector_temp[1]=input_vector[0]+input_vector[2]

    input_vector_temp[2]=input_vector[0]+input_vector[3]

  4. std::accumulate的逻辑较为复杂,静态难以推导,使用动态调试进行查看

  5. std::accumulate完成后,将input_vector_fib_vector进行比较

  6. std::back_insert_iterator<std::vector<int,std::allocator<int>>>,main::{lambda(int)#3}>input_vector中的奇数填入flag

进行动态调试

输入数据为51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

将断点下在std::vector<int,std::allocator<int>>::vector(&flag, argv, v8);

完成对input_vector的写入后对其中的数据进行查看

双击input_vector查看栈状态

根据栈中的内容01ACC2F0进入堆中查看


完成对fib_vector的写入后对其中的数据进行查看

双击fib_vector查看栈状态

根据栈中的内容01ACC340进入堆中查看


完成std::transform后对input_vector_temp进行查看

双击input_vector_temp查看栈状态

根据栈中的内容01ACC390进入堆中查看


完成std::accumulate后对input_vector_进行查看

双击input_vector_查看栈状态

根据栈中的内容01ACC560进入堆中查看

可以看到std::accumulate主要对input_vector_temp进行倒序处理

由此可得exp.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def fib(a):
if a==0 or a==1:
return 1
return fib(a-1)+fib(a-2)
flag=[]
for i in range(16):
flag.append(fib(i))
flag=flag[::-1]
for i in range(1,16):
flag[i]-=flag[0]
for i in range(16):
print(flag[i],end=" ")
print()
print()
print("flag{",end="")
for i in range(16):
if flag[i]%2:
print(flag[i],end="")
print("}")
1
2
3
987 -377 -610 -754 -843 -898 -932 -953 -966 -974 -979 -982 -984 -985 -986 -986 

flag{987-377-843-953-979-985}

将结果作为程序运行输入

CSAW CTF 2014

csaw2013reversing2

  • 静态调试
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // ecx
CHAR *lpMem; // [esp+8h] [ebp-Ch]
HANDLE hHeap; // [esp+10h] [ebp-4h]

hHeap = HeapCreate(0x40000u, 0, 0);
lpMem = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);
memcpy_s(lpMem, MaxCount, &unk_409B10, MaxCount);
if ( sub_40102A() || IsDebuggerPresent() )
{
__debugbreak();
sub_401000(v3 + 4, lpMem);
ExitProcess(0xFFFFFFFF);
}
MessageBoxA(0, lpMem + 1, "Flag", 2u);
HeapFree(hHeap, 0, lpMem);
HeapDestroy(hHeap);
ExitProcess(0);
}

HeapCreate:Creates a private heap object that can be used by the calling process. The function reserves space in the virtual address space of the process and allocates physical storage for a specified initial portion of this block.(在进程中创建堆栈)

https://docs.microsoft.com/zh-cn/windows/win32/api/heapapi/nf-heapapi-heapcreate

HeapAlloc:Allocates a block of memory from a heap. The allocated memory is not movable.(在指定的堆上分配内存)

https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc

sub_40102A()是一个永远返回0的函数

IsDebuggerPresent():Determines whether the calling process is being debugged by a user-mode debugger.(确定调用进程是否由用户模式的调试器调试,用来反调试)

https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent

MessageBoxA(0, lpMem + 1, "Flag", 2u)这个函数直接将lpMem输出,而lpMem中的内容并非ascii,因此造成乱码

正确流程应为进入if中的sub_401000(v3 + 4, lpMem)函数中,对lpMem进行转换,得到正确的flag

sub_401000(v3 + 4, lpMem)函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
unsigned int __fastcall sub_401000(int a1, int a2)
{
int v2; // esi
unsigned int v3; // eax
unsigned int v4; // ecx
unsigned int result; // eax

v2 = dword_409B38;
v3 = a2 + 1 + strlen((const char *)(a2 + 1)) + 1;
v4 = 0;
result = ((v3 - (a2 + 2)) >> 2) + 1;
if ( result )
{
do
*(_DWORD *)(a2 + 4 * v4++) ^= v2;
while ( v4 < result );
}
return result;
}

lpMem的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.data:00409B10 unk_409B10      db 0BBh                 ; DATA XREF: _main+33↑o
.data:00409B11 db 0CCh
.data:00409B12 db 0A0h
.data:00409B13 db 0BCh
.data:00409B14 db 0DCh
.data:00409B15 db 0D1h
.data:00409B16 db 0BEh
.data:00409B17 db 0B8h
.data:00409B18 db 0CDh
.data:00409B19 db 0CFh
.data:00409B1A db 0BEh
.data:00409B1B db 0AEh
.data:00409B1C db 0D2h
.data:00409B1D db 0C4h
.data:00409B1E db 0ABh
.data:00409B1F db 82h
.data:00409B20 db 0D2h
.data:00409B21 db 0D9h
.data:00409B22 db 93h
.data:00409B23 db 0B3h
.data:00409B24 db 0D4h
.data:00409B25 db 0DEh
.data:00409B26 db 93h
.data:00409B27 db 0A9h
.data:00409B28 db 0D3h
.data:00409B29 db 0CBh
.data:00409B2A db 0B8h
.data:00409B2B db 82h
.data:00409B2C db 0D3h
.data:00409B2D db 0CBh
.data:00409B2E db 0BEh
.data:00409B2F db 0B9h
.data:00409B30 db 9Ah
.data:00409B31 db 0D7h
.data:00409B32 db 0CCh
.data:00409B33 db 0DDh

dword_409B38的内容

1
.data:00409B38 dword_409B38    dd 0DDCCAABBh

P.S.1:语句*(_DWORD *)(a2 + 4 * v4++) ^= v2;说明a2中的值为每四个hexv2进行一次异或

P.S.2:注意大小端

1
2
3
4
5
6
7
v2=0xBBAACCDD
a2=[0xBBCCA0BC,0xDCD1BEB8,0xCDCFBEAE,0xD2C4AB82,0xD2D993B3,0xD4DE93A9,0xD3CBB882,0xD3CBBEB9,0x9AD7CCDD]
flag=""
for i in range(9):
flag+=format((a2[i]^v2),"x")
print(flag)
print(bytearray.fromhex(flag).decode())

flag{reversing_is_not_that_hard!}

  • 动态调试

由于在if的条件判断中存在IsDebuggerPresent(),这个函数在汇编中添加了int3这个断点,因此可以尝试在x32dbg中将int3修改为nop

csaw-ctf-2016-quals

gametime

游戏题目,利用动态调试进行

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // edi
unsigned int v4; // eax
int v5; // ecx
int v6; // ecx
int v7; // ecx
void (__stdcall *v8)(DWORD); // ebx
signed int v9; // esi
signed int v10; // esi
signed int v11; // esi
signed int v12; // esi
signed int v13; // esi
signed int v14; // edi
int v15; // esi
int *v16; // esi
signed int v17; // ebx
DWORD separate_time; // ST3C_4
int v19; // esi
int v20; // eax
int v21; // esi
int v22; // eax
char v23; // cl
int v24; // eax
int v26; // [esp+10h] [ebp-20h]
int v27; // [esp+14h] [ebp-1Ch]
char v28; // [esp+1Bh] [ebp-15h]
int v29; // [esp+1Ch] [ebp-14h]
int v30; // [esp+22h] [ebp-Eh]
int v31; // [esp+26h] [ebp-Ah]
__int16 v32; // [esp+2Ah] [ebp-6h]

LOWORD(v29) = 32;
v27 = 7630702;
*(int *)((char *)&v29 + 2) = 0;
v30 = 0;
v31 = 0;
v32 = 0;
v3 = 0;
v26 = 0;
print_out((int)"\r\tZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMG\n");
print_out((int)"\tkey is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\r\tZOMGZOMG ZOMGZOMG\n");
print_out((int)"\tkey is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\r\tZOMGZOMG TAP TAP REVOLUTION!!!!!!! ZOMGZOMG\n");
print_out((int)"\tkey is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\r\tZOMGZOMG ZOMGZOMG\n");
print_out((int)"\tkey is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\r\tZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMGZOMGZOMGOZMG\n\n\n");
print_out((int)"\tkey is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\r\t R U READDY?!\n\n\n");
print_out((int)"\tkey is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\rThe game is starting in...\n");
v4 = _time64(0);
srand(v4);
Countdown();
get_ready_to_play(200u);
if ( !sub_B81435(0x1F4u, ' ', 10, v5, (int)&v29, (int)&v27) )
return 0;
if ( !sub_B81435(0x12Cu, 'x', 8, v6, (int)&v29, (int)&v27) )
return 0;
if ( !sub_B81435(0x12Cu, 'm', 5, v7, (int)&v29, (int)&v27) )
return 0;
print_out((int)"key is %s (%s)", &v27, &v29);
print_out((int)"\rTRAINING COMPLETE! \n");
v8 = Sleep;
v9 = 20;
do
{
Sleep(0xC8u);
print_out((int)"\n");
--v9;
}
while ( v9 );
print_out((int)"key is %s (%s)", &v27, &v29);
print_out((int)"\rNow you know everything you need to know");
v10 = 4;
do
{
print_out((int)".");
Sleep(0x3E8u);
--v10;
}
while ( v10 );
print_out((int)"\n\n\nfor the rest of your life!\n");
v11 = 20;
do
{
Sleep(0xC8u);
print_out((int)"\n");
--v11;
}
while ( v11 );
print_out((int)"LETS PLAY !\n");
v12 = 20;
do
{
Sleep(0xC8u);
print_out((int)"\n");
--v12;
}
while ( v12 );
Countdown();
get_ready_to_play(100u);
if ( !sub_B81507(5, ' ', 200u, (int)&v29, (int)&v27) )
return 0;
if ( !sub_B81507(2, 'x', 200u, (int)&v29, (int)&v29) )
return 0;
if ( !sub_B81507(1, 'm', 200u, (int)&v29, (int)&v29) )
return 0;
print_out((int)"key is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\rooooh, you fancy!!!\n");
if ( !sub_B81507(5, 'm', 200u, (int)&v29, (int)&v27)// first_arg为输出的.的数量
|| !sub_B81507(2, 'x', 200u, (int)&v29, (int)&v27)
|| !sub_B81507(1, ' ', 200u, (int)&v29, (int)&v27) )
{
return 0;
}
print_out((int)"key is %s (%s)", &v27, &v29);
print_out((int)"\b\b");
print_out((int)"NIIICE JOB)!!!!\n");
v13 = 20;
do
{
Sleep(0x32u);
print_out((int)"\n");
--v13;
}
while ( v13 );
v28 = 1;
do
{
if ( v3 % 3 == 1 )
{
print_out((int)"key is %s (%s)", &v27, &v29);
sub_B81423();
print_out((int)"\rTURBO TIME! \n");
v14 = 0;
do
{
v8(0x32u);
print_out((int)"\n");
if ( v14 == 19 )
{
v15 = sub_B8141D();
sub_B81D02(&v29, v15 - 5514);
MEMORY[0xB9A1F8] = &v29;
MEMORY[0xB9A1FC] = v15 - 5498;
sub_B81AA5();
sub_B81CC9();
print_out((int)"key is %s (%s)", &unk_B97D02, &v27);
print_out((int)"\b\b");
v16 = &v29;
v17 = 16;
do
{
separate_time = *(unsigned __int8 *)v16;
print_out((int)"%02x");
v16 = (int *)((char *)v16 + 1);
--v17;
}
while ( v17 );
print_out((int)")\n\n");
v8 = Sleep;
}
++v14;
}
while ( v14 < 20 );
v19 = 0;
while ( 1 )
{
v20 = rand();
if ( !sub_B81507(1, byte_B97B08[v20 % 3], 100u, (int)&v29, (int)&v27) )
break;
if ( ++v19 >= 10 )
goto LABEL_33;
}
v28 = 0;
LABEL_33:
v3 = v26;
}
v21 = 0;
while ( 1 )
{
v22 = rand();
v23 = v28;
v24 = v22 % 3;
if ( v28 )
break;
LABEL_38:
if ( ++v21 >= 10 )
goto LABEL_41;
}
if ( sub_B81507(v24 + 3, byte_B97B08[v24], 100u, (int)&v29, (int)&v27) )
{
v23 = v28;
goto LABEL_38;
}
v23 = 0;
v28 = 0;
LABEL_41:
if ( v3 == 1337 )
{
success();
v23 = v28;
}
v26 = ++v3;
}
while ( v23 );
return 0;
}

关键部分(即对输入进行处理)

1
2
3
if ( !sub_B81507(5, 'm', 200u, (int)&v29, (int)&v27)// first_arg(5,2,1)为输出的.的数量
|| !sub_B81507(2, 'x', 200u, (int)&v29, (int)&v27)
|| !sub_B81507(1, ' ', 200u, (int)&v29, (int)&v27) )

进入该函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
char __usercall sub_B81507@<al>(int a1@<edx>, int a2@<ecx>, DWORD dwMilliseconds, int a4, int a5)
{
int v5; // esi
int input_char; // ebx

v5 = a1;
input_char = a2;
print_out((int)"key is %s (%s)", a5, a4);
sub_B81423();
print_out((int)"\r \r");
if ( v5 > 0 )
{
do
{
print_out((int)".");
Sleep(dwMilliseconds);
--v5;
}
while ( v5 );
}
if ( sub_B81260(input_char, 500 * dwMilliseconds) )
return 1;
print_out((int)"key is %s (%s)\r", a5, a4);
print_out((int)"UDDER FAILURE! http://imgur.com/4Ajx21P \n");
return 0;
}

前半部分为输出key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
v5 = a1;
input_char = a2;
print_out((int)"key is %s (%s)", a5, a4);
sub_B81423();
print_out((int)"\r \r");
if ( v5 > 0 )
{
do
{
print_out((int)".");
Sleep(dwMilliseconds);
--v5;
}
while ( v5 );
}

此处为关键部分,用于判断输入并进行计时

1
2
if ( sub_B81260(input_char, 500 * dwMilliseconds) )
return 1;

进入函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bool __fastcall sub_B81260(int a1, int a2)
{
int input_char; // edi
int v3; // esi
int v4; // eax

input_char = a1;
v3 = a2;
if ( a1 == ' ' )
print_out((int)&unk_B97868);
else
print_out((int)&unk_B9786C, a1);
if ( v3 )
{
while ( !_kbhit() ) // 时间限制
{
if ( !--v3 )
goto LABEL_7;
}
v4 = _getch();
}
else
{
LABEL_7:
v4 = -1;
}
return v4 != -1 && v4 == input_char;
}

如果超时,则会跳转到LABEL_7,则游戏失败,因此,尝试在goto LABEL_7处下断点进行调试

将断点下在B81294

Hack-you-2014

Newbie_calculations

通过观察反汇编,三个函数分别为加减乘

将c代码转换成python代码,直接得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
def mul(a,b):
return a*b
def sub(a,b):
return a-b
def add(a,b):
return a+b

v120=[1 for i in range(32)]
v121 = 0
v120[0] = mul(v120[0], 1000000000)
v120[0] = sub(v120[0], 999999950)
v120[0] = mul(v120[0], 2)

v120[1] = add(v120[1], 5000000)
v120[1] = sub(v120[1], 6666666)
v120[1] = add(v120[1], 1666666)
v120[1] = add(v120[1], 45)
v120[1] = mul(v120[1], 2)
v120[1] = add(v120[1], 5)

v120[2] = mul(v120[2], 1000000000)
v120[2] = sub(v120[2], 999999950)
v120[2] = mul(v120[2], 2)
v120[2] = add(v120[2], 2)

v120[3] = add(v120[3], 55)
v120[3] = sub(v120[3], 3)
v120[3] = add(v120[3], 4)
v120[3] = sub(v120[3], 1)

v120[4] = mul(v120[4], 100000000)
v120[4] = sub(v120[4], 99999950)
v120[4] = mul(v120[4], 2)
v120[4] = add(v120[4], 2)

v120[5] = sub(v120[5], 1)
v120[5] = mul(v120[5], 1000000000)
v120[5] = add(v120[5], 55)
v120[5] = sub(v120[5], 3)

v120[6] = mul(v120[6], 1000000)
v120[6] = sub(v120[6], 999975)
v120[6] = mul(v120[6], 4)

v120[7] = add(v120[7], 55)
v120[7] = sub(v120[7], 33)
v120[7] = add(v120[7], 44)
v120[7] = sub(v120[7], 11)

v120[8] = mul(v120[8], 10)
v120[8] = sub(v120[8], 5)
v120[8] = mul(v120[8], 8)
v120[8] = add(v120[8], 9)

v120[9] = add(v120[9], 0)
v120[9] = sub(v120[9], 0)
v120[9] = add(v120[9], 11)
v120[9] = sub(v120[9], 11)
v120[9] = add(v120[9], 53)

v120[10] = add(v120[10], 49)
v120[10] = sub(v120[10], 2)
v120[10] = add(v120[10], 4)
v120[10] = sub(v120[10], 2)

v120[11] = mul(v120[11], 1000000)
v120[11] = sub(v120[11], 999999)
v120[11] = mul(v120[11], 4)
v120[11] = add(v120[11], 50)

v120[12] = add(v120[12], 1)
v120[12] = add(v120[12], 1)
v120[12] = add(v120[12], 1)
v120[12] = add(v120[12], 1)
v120[12] = add(v120[12], 1)
v120[12] = add(v120[12], 1)
v120[12] = add(v120[12], 10)
v120[12] = add(v120[12], 32)

v120[13] = mul(v120[13], 10)
v120[13] = sub(v120[13], 5)
v120[13] = mul(v120[13], 8)
v120[13] = add(v120[13], 9)
v120[13] = add(v120[13], 48)

v120[14] = sub(v120[14], 1)
v120[14] = mul(v120[14], -294967296)
v120[14] = add(v120[14], 55)
v120[14] = sub(v120[14], 3)

v120[15] = add(v120[15], 1)
v120[15] = add(v120[15], 2)
v120[15] = add(v120[15], 3)
v120[15] = add(v120[15], 4)
v120[15] = add(v120[15], 5)
v120[15] = add(v120[15], 6)
v120[15] = add(v120[15], 7)
v120[15] = add(v120[15], 20)

v120[16] = mul(v120[16], 10)
v120[16] = sub(v120[16], 5)
v120[16] = mul(v120[16], 8)
v120[16] = add(v120[16], 9)
v120[16] = add(v120[16], 48)

v120[17] = add(v120[17], 7)
v120[17] = add(v120[17], 6)
v120[17] = add(v120[17], 5)
v120[17] = add(v120[17], 4)
v120[17] = add(v120[17], 3)
v120[17] = add(v120[17], 2)
v120[17] = add(v120[17], 1)
v120[17] = add(v120[17], 20)

v120[18] = add(v120[18], 7)
v120[18] = add(v120[18], 2)
v120[18] = add(v120[18], 4)
v120[18] = add(v120[18], 3)
v120[18] = add(v120[18], 6)
v120[18] = add(v120[18], 5)
v120[18] = add(v120[18], 1)
v120[18] = add(v120[18], 20)

v120[19] = mul(v120[19], 1000000)
v120[19] = sub(v120[19], 999999)
v120[19] = mul(v120[19], 4)
v120[19] = add(v120[19], 50)
v120[19] = sub(v120[19], 1)

v120[20] = sub(v120[20], 1)
v120[20] = mul(v120[20], -294967296)
v120[20] = add(v120[20], 49)
v120[20] = sub(v120[20], 1)

v120[21] = sub(v120[21], 1)
v120[21] = mul(v120[21], 1000000000)
v120[21] = add(v120[21], 54)
v120[21] = sub(v120[21], 1)
v120[21] = add(v120[21], 1000000000)
v120[21] = sub(v120[21], 1000000000)

v120[22] = add(v120[22], 49)
v120[22] = sub(v120[22], 1)
v120[22] = add(v120[22], 2)
v120[22] = sub(v120[22], 1)

v120[23] = mul(v120[23], 10)
v120[23] = sub(v120[23], 5)
v120[23] = mul(v120[23], 8)
v120[23] = add(v120[23], 9)
v120[23] = add(v120[23], 48)

v120[24] = add(v120[24], 1)
v120[24] = add(v120[24], 3)
v120[24] = add(v120[24], 3)
v120[24] = add(v120[24], 3)
v120[24] = add(v120[24], 6)
v120[24] = add(v120[24], 6)
v120[24] = add(v120[24], 6)
v120[24] = add(v120[24], 20)

v120[25] = add(v120[25], 55)
v120[25] = sub(v120[25], 33)
v120[25] = add(v120[25], 44)
v120[25] = sub(v120[25], 11)
v120[25] = add(v120[25], 42)

v120[26] = add(v120[26], v120[25])

v120[27] = add(v120[27], v120[12])

v120[27] = v120[27]
v120[28] = sub(v120[28], 1)
v120[28] = add(v120[28], v120[27])
v120[28] = sub(v120[28], 1)

v120[23] = v120[23]
v120[29] = sub(v120[29], 1)
v120[29] = mul(v120[29], 1000000)
v120[29] = add(v120[29], v120[23])
v120[27] = v120[27]
v120[30] = add(v120[30], 1)
v120[30] = mul(v120[30], v120[27])
v120[31] = add(v120[31], v120[30])
for i in v120:
print(chr(i),end="")

daf8f4d816261a41a115052a1bc21ade

mma-ctf-2nd-2016

reverse-box

题目提示

$ ./reverse_box ${FLAG}
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl main(int a1, char **a2)
{
size_t i; // [esp+18h] [ebp-10Ch]
int v4; // [esp+1Ch] [ebp-108h]
unsigned int v5; // [esp+11Ch] [ebp-8h]

v5 = __readgsdword(0x14u);
if ( a1 <= 1 )
{
printf("usage: %s flag\n", *a2);
exit(1);
}
sub_804858D(&v4);
for ( i = 0; i < strlen(a2[1]); ++i )
printf("%02x", *(&v4 + a2[1][i]));
putchar('\n');
return 0;
}
sub_804858D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
int __cdecl sub_804858D(_BYTE *a1)
{
unsigned int v1; // eax
int v2; // edx
char v3; // al
char v4; // ST1B_1
char v5; // al
int result; // eax
unsigned __int8 v7; // [esp+1Ah] [ebp-Eh]
char v8; // [esp+1Bh] [ebp-Dh]
char v9; // [esp+1Bh] [ebp-Dh]
int v10; // [esp+1Ch] [ebp-Ch]

v1 = time(0);
srand(v1);
do
v10 = rand(); // &0xff
while ( !v10 );
*a1 = v10;
v7 = 1;
v8 = 1;
do
{
v2 = v7 ^ 2 * v7; // v7^(v7<<1)
if ( (v7 & 0x80u) == 0 )
v3 = 0;
else
v3 = 0x1B;
v7 = v2 ^ v3;
v4 = 4 * (2 * v8 ^ v8) ^ 2 * v8 ^ v8;
v9 = 16 * v4 ^ v4;
if ( v9 >= 0 )
v5 = 0;
else
v5 = 9;
v8 = v9 ^ v5;
result = __ROR1__(v8, 4) ^ __ROR1__(v8, 5) ^ __ROR1__(v8, 6) ^ __ROR1__(v8, 7) ^ (v8 ^ *a1);
a1[v7] = result;
}
while ( v7 != 1 );
return result;
}

sub_804858D函数根据一个在00xff之间的随机数,生成了一个长度为256的随机数组,根据题目提示输入flag得到的结果进行反推,进而得到flag,flag的头部为TWCTF,由此进行爆破

使用pwntools进行爆破

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
import time
payload="TWCTF{1234567890-=!@#$%^&*()_+qwertyuiop[]\\asdfghjkl;'zxcvbnm,./QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?}"
target="95eeaf95ef"
a=[]
while a[0:10]!=target:
p = process(argv=["/home/misaka/Downloads/reverse_box", payload])
a=bytes.decode(p.recvline(keepends=False))
p.recvall()
time.sleep(1)
print(a)
print(a[0:10])

得到字符串中每个字符对应的hex为95eeaf95ef94729676ad23b02fb2a7b16d9248bc93838aed425081107a441640f8f52703284c1de48cf9ff5a3af68630f0b7cae557796f094e8d1f2a89c484a064eedbb5957e498e31e6944aa53658aeef15e763069c35260bdfaf04999a565e07c04a

根据hex构建字典进行推导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a="95eeaf95ef94729676ad23b02fb2a7b16d9248bc93838aed425081107a441640f8f52703284c1de48cf9ff5a3af68630f0b7cae557796f094e8d1f2a89c484a064eedbb5957e498e31e6944aa53658aeef15e763069c35260bdfaf04999a565e07c04a"
b="TWCTF{1234567890-=!@#$%^&*()_+qwertyuiop[]\\asdfghjkl;'zxcvbnm,./QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?}"
flag_hex="95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a"
list_a=[]
list_flag=[]
for i in range(0,len(a),2):
list_a.append("0x"+a[i]+a[i+1])
for i in range(0,len(flag_hex),2):
list_flag.append("0x"+flag_hex[i]+flag_hex[i+1])
print(list_flag)
for i in range(len(b)):
print("\"",list_a[i],"\"",":","\"",b[i],"\"",sep="",end=",")
#"0x95":"T","0xee":"W","0xaf":"C","0x95":"T","0xef":"F","0x94":"{","0x72":"1","0x96":"2","0x76":"3","0xad":"4","0x23":"5","0xb0":"6","0x2f":"7","0xb2":"8","0xa7":"9","0xb1":"0","0x6d":"-","0x92":"=","0x48":"!","0xbc":"@","0x93":"#","0x83":"$","0x8a":"%","0xed":"^","0x42":"&","0x50":"*","0x81":"(","0x10":")","0x7a":"_","0x44":"+","0x16":"q","0x40":"w","0xf8":"e","0xf5":"r","0x27":"t","0x03":"y","0x28":"u","0x4c":"i","0x1d":"o","0xe4":"p","0x8c":"[","0xf9":"]","0xff":"\","0x5a":"a","0x3a":"s","0xf6":"d","0x86":"f","0x30":"g","0xf0":"h","0xb7":"j","0xca":"k","0xe5":"l","0x57":";","0x79":"'","0x6f":"z","0x09":"x","0x4e":"c","0x8d":"v","0x1f":"b","0x2a":"n","0x89":"m","0xc4":",","0x84":".","0xa0":"/","0x64":"Q","0xee":"W","0xdb":"E","0xb5":"R","0x95":"T","0x7e":"Y","0x49":"U","0x8e":"I","0x31":"O","0xe6":"P","0x94":"{","0x4a":"}","0xa5":"|","0x36":"A","0x58":"S","0xae":"D","0xef":"F","0x15":"G","0xe7":"H","0x63":"J","0x06":"K","0x9c":"L","0x35":":","0x26":""","0x0b":"Z","0xdf":"X","0xaf":"C","0x04":"V","0x99":"B","0x9a":"N","0x56":"M","0x5e":"<","0x07":">","0xc0":"?","0x4a":"}"
print()
dic={"0x95":"T","0xee":"W","0xaf":"C","0x95":"T","0xef":"F","0x94":"{","0x72":"1","0x96":"2","0x76":"3","0xad":"4","0x23":"5","0xb0":"6","0x2f":"7","0xb2":"8","0xa7":"9","0xb1":"0","0x6d":"-","0x92":"=","0x48":"!","0xbc":"@","0x93":"#","0x83":"$","0x8a":"%","0xed":"^","0x42":"&","0x50":"*","0x81":"(","0x10":")","0x7a":"_","0x44":"+","0x16":"q","0x40":"w","0xf8":"e","0xf5":"r","0x27":"t","0x03":"y","0x28":"u","0x4c":"i","0x1d":"o","0xe4":"p","0x8c":"[","0xf9":"]","0xff":"\\","0x5a":"a","0x3a":"s","0xf6":"d","0x86":"f","0x30":"g","0xf0":"h","0xb7":"j","0xca":"k","0xe5":"l","0x57":";","0x79":"'","0x6f":"z","0x09":"x","0x4e":"c","0x8d":"v","0x1f":"b","0x2a":"n","0x89":"m","0xc4":",","0x84":".","0xa0":"/","0x64":"Q","0xee":"W","0xdb":"E","0xb5":"R","0x95":"T","0x7e":"Y","0x49":"U","0x8e":"I","0x31":"O","0xe6":"P","0x94":"{","0x4a":"}","0xa5":"|","0x36":"A","0x58":"S","0xae":"D","0xef":"F","0x15":"G","0xe7":"H","0x63":"J","0x06":"K","0x9c":"L","0x35":":","0x26":"\"","0x0b":"Z","0xdf":"X","0xaf":"C","0x04":"V","0x99":"B","0x9a":"N","0x56":"M","0x5e":"<","0x07":">","0xc0":"?","0x4a":"}"}
print(len(list_flag))
for i in list_flag:
print(dic[i],end="")

得到flagTWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}

NJUPT CTF 2017

maze

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
signed __int64 v3; // rbx
signed int v4; // eax
bool v5; // bp
bool v6; // al
const char *v7; // rdi
__int64 v9; // [rsp+0h] [rbp-28h]

v9 = 0LL;
puts("Input flag:");
scanf("%s", &input, 0LL);
if ( strlen(&input) != 24 || strncmp(&input, "nctf{", 5uLL) || *(&byte_6010BF + 24) != '}' )// 输入长度为24,格式为nctf{xxx}
{
LABEL_22:
puts("Wrong flag!");
exit(-1);
}
v3 = 5LL;
if ( strlen(&input) - 1 > 5 )
{
while ( 1 )
{
v4 = *(&input + v3); // 先取第五位
v5 = 0;
if ( v4 > 'N' )
{
v4 = (unsigned __int8)v4;
if ( (unsigned __int8)v4 == 'O' )
{
v6 = Left((_DWORD *)&v9 + 1); // v7=((&v9+1)的ascii>0),即越界判断,同时(&v9+1)的ascii-1
// 向左
goto LABEL_14;
}
if ( v4 == 'o' )
{
v6 = Right((int *)&v9 + 1); // v7=(((&v9+1)的ascii+1)<8),同时(&v9+1)的ascii+1
// 向右
goto LABEL_14;
}
}
else
{
v4 = (unsigned __int8)v4;
if ( (unsigned __int8)v4 == '.' )
{
v6 = Up(&v9); // v6=(v9>0)(减一之前),v9的值-1
// 向上
goto LABEL_14;
}
if ( v4 == '0' )
{
v6 = Down((int *)&v9); // v6=(v9+1)<8,v9的值+1
// 向下
LABEL_14:
v5 = v6;
goto LABEL_15;
}
}
LABEL_15:
if ( !(unsigned __int8)Check((__int64)maze, SHIDWORD(v9), v9) )// asc=' ******* * **** * **** * *** *# *** *** *** *********'
goto LABEL_22;
if ( ++v3 >= strlen(&input) - 1 )
{
if ( v5 )
break;
LABEL_20:
v7 = "Wrong flag!";
goto LABEL_21;
}
}
}
if ( maze[8 * (signed int)v9 + SHIDWORD(v9)] != '#' )// 说明v9的低位是行移动即上下移动,v9的高位是列移动即左右移动
goto LABEL_20;
v7 = "Congratulations!";
LABEL_21:
puts(v7);
return 0LL;
}
  1. 将迷宫提取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
asc=' ******* * **** * **** * *** *# *** *** *** *********'
asc=list(asc)
asc=np.array(asc).reshape(8,8)
print(asc)
'''
[[' ' ' ' '*' '*' '*' '*' '*' '*']
['*' ' ' ' ' ' ' '*' ' ' ' ' '*']
['*' '*' '*' ' ' '*' ' ' '*' '*']
['*' '*' ' ' ' ' '*' ' ' '*' '*']
['*' ' ' ' ' '*' '#' ' ' ' ' '*']
['*' '*' ' ' '*' '*' '*' ' ' '*']
['*' '*' ' ' ' ' ' ' ' ' ' ' '*']
['*' '*' '*' '*' '*' '*' '*' '*']]

00111111
10001001
11101011
11001011
1001#001
11011101
11000001
11111111
'''
  1. 确定移动方向所代表的函数以及所使用的代表字符
1
if ( maze[8 * (signed int)v9 + SHIDWORD(v9)] != '#' )// 说明v9的低位是行移动即上下移动,v9的高位是列移动即左右移动

而根据移动函数的边界判断可以确认该函数的移动方向,由此可以确认函数和函数所使用的字符

  1. 走迷宫
1
2
3
4
dic={"上":".","下":"0","左":"O","右":"o"}
answer="右下右右下下左下下下右右右右上上左左"
for i in answer:
print(dic[i],end="")

flag:nctf{o0oo00O000oooo..OO}

nullcon-hackim-2016

zorropub

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
int __fastcall main(__int64 a1, char **a2, char **a3)
{
size_t v3; // rax
int num; // [rsp+1Ch] [rbp-104h]
int id; // [rsp+20h] [rbp-100h]
int i; // [rsp+24h] [rbp-FCh]
unsigned int seed; // [rsp+28h] [rbp-F8h]
unsigned int v9; // [rsp+2Ch] [rbp-F4h]
char v10; // [rsp+30h] [rbp-F0h]
char v11[16]; // [rsp+90h] [rbp-90h]
char flag[32]; // [rsp+A0h] [rbp-80h]
char s; // [rsp+C0h] [rbp-60h]
char s1[40]; // [rsp+E0h] [rbp-40h]
unsigned __int64 v15; // [rsp+108h] [rbp-18h]

v15 = __readfsqword(0x28u);
seed = 0;
puts("Welcome to Pub Zorro!!");
printf("Straight to the point. How many drinks you want?", a2);
__isoc99_scanf("%d", &num);
if ( num <= 0 )
{
printf("You are too drunk!! Get Out!!", &num);
exit(-1);
}
printf("OK. I need details of all the drinks. Give me %d drink ids:", num);
for ( i = 0; i < num; ++i )
{
__isoc99_scanf("%d", &id);
if ( id <= 16 || id > 65535 )
{
puts("Invalid Drink Id.");
printf("Get Out!!", &id);
exit(-1);
}
seed ^= id;
}
i = seed;
v9 = 0;
while ( i )
{
++v9;
i &= i - 1;
}
if ( v9 != 10 )
{
puts("Looks like its a dangerous combination of drinks right there.");
puts("Get Out, you will get yourself killed");
exit(-1);
}
srand(seed);
MD5_Init(&v10);
for ( i = 0; i <= 29; ++i )
{
v9 = rand() % 1000;
sprintf(&s, "%d", v9);
v3 = strlen(&s);
MD5_Update(&v10, &s, v3);
flag[i] = v9 ^ LOBYTE(unk_6020C0[i]);
}
flag[i] = 0;
MD5_Final(v11, &v10);
for ( i = 0; i <= 15; ++i )
sprintf(&s1[2 * i], "%02x", v11[i]); // v11转16进制保存在s1中
if ( strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )
{
puts("Try different mix, This mix is too sloppy");
exit(-1);
}
return printf("\nYou choose right mix and here is your reward: The flag is nullcon{%s}\n", flag);
}

根据逻辑在Linux下进行爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "stdio.h"
#include "stdlib.h"
#include "openssl/md5.h"
#include "string.h"

int main(){
for(int seed=17;seed<=65535;++seed){
int i=seed,v9=0;
while(i){
++v9;
i&=i-1;
}
if(v9==10){
srand(seed);
MD5_CTX v10;
MD5_Init(&v10);
unsigned char v11[16];
char s1[40];
for (i=0;i<=29;++i){
v9=rand()%1000;
char s[5];
sprintf(s,"%d", v9);
s[4]=0;
int v3=strlen(s);
MD5_Update(&v10,s,v3);
}
MD5_Final(v11,&v10);
for(i=0;i<=15;++i)
sprintf(&s1[2*i],"%02x",v11[i]); // v11转16进制保存在s1中
if(!strcmp(s1,"5eba99aff105c9ff6a1a913e343fec67")){
printf("%d",seed);
}
}
}
return 0;
}

gcc test.c -lcrypto -o test

得到seed59306

school-ctf-winter-2015

parallel-comparator-200

1
2
3
4
for (i = 0; i < FLAG_LEN; i++) {
if (generated_string[i] != just_a_string[i])//gen==just a string
return 0;
}

说明generated_string[i] == just_a_string[i]

generated_string[i] = *(char *)result + just_a_string[i];知,result等于0

1
2
*result = (argument[0]+argument[1]) ^ argument[2];//(first_letter+difference)^user_string=0
return result;//null

返回的resultNULL,(first_letter+difference)^user_string=0,first_letter+difference=user_string

1
2
3
4
5
6
7
difference=[0, 9, -9, -1, 13, -13, -4, -11, -9, -1, -7, 6, -13, 13, 3, 9, -13, -11, 6, -7]
for first_letter in range(97,123):
user_string=""
for i in range(20):
user_string+=chr(first_letter+difference[i])
print(user_string)
#lucky_hacker_you_are

flag:lucky_hacker_you_are

P.S.

在Linux环境下

1
2
3
4
while ((initialization_number = random()) >= 64);

int first_letter;
first_letter = (initialization_number % 26) + 97;

initialization_number恒为37,first_letter恒为108,因为只有random而没有srand

1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

int main(){
int a;
while ((a=random())>=64);
int f=(a%26)+97;
printf("a=%d,f=%d",a,f);
return 0;
}

a=37,f=108

然而在Windows环境下

first_letter恒为112

SharifCTF 2016

getit

  • 静态方法
1
2
3
4
5
6
7
8
9
10
LODWORD(v5) = 0;
while ( (signed int)v5 < strlen(s) ) // 长度为32
{
if ( v5 & 1 )
v3 = 1;
else
v3 = -1;
*(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;// s="c61b68366edeb7bdce3c6820314b7498"
LODWORD(v5) = v5 + 1;
}

把上述代码改写成python,即可得到flag

1
2
3
4
5
6
7
8
9
10
11
12
v5=0
v3=0
s="c61b68366edeb7bdce3c6820314b7498"
while v5<len(s):
if v5&1:
v3=1
else:
v3=-1
print(chr(ord(s[v5])+v3),end="")
v5+=1
print()
a=[24,25,32,40,36,28,17,34,39,16,33,19,26,5,3,29,27,31,4,8,15,37,42,14,41,2,23,21,0,10,20,7,11,1,13,6,38,18,35,12,22,9]

flag:SharifCTF{b70c59275fcfa8aebf2d5911223c6589}

  • 动态方法

0x400824处下断点

SHCTF-2017

crackme

PEiD查壳(北斗3.7)

x32dbg载入,运行到pushad,记录ESP地址,在内存窗口中下断点

再次运行,达到jmp,可知OEP为401336

使用插件中的Scylla进行dump

PEiD再次查壳

进行静态分析

main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int v4; // eax
char v5; // [esp+4h] [ebp-38h]
char v6; // [esp+5h] [ebp-37h]

v5 = 0;
sub_4018F4(&v6, 0, 49);
MEMORY[0x6BF831D1]("Please Input Flag:");
MEMORY[0x6BF82E80](&v5, 44);
if ( strlen(&v5) == 42 )
{
v4 = 0;
while ( (*(&v5 + v4) ^ byte_402130[v4 % 16]) == dword_402150[v4] )
{
if ( ++v4 >= 42 )
{
MEMORY[0x6BF831D1]("right!\n");
goto LABEL_8;
}
}
MEMORY[0x6BF831D1]("error!\n");
LABEL_8:
result = 0;
}
else
{
MEMORY[0x6BF831D1]("error!\n");
result = -1;
}
return result;
}

byte_402130为this_is_not_flag

dword_402150

1
2
3
4
a="this_is_not_flag"
b=[18, 4, 8, 20, 36, 92, 74, 61, 86, 10, 16, 103, 0, 65, 0, 1, 70, 90, 68, 66, 110, 12, 68, 114, 12, 13, 64, 62, 75, 95, 2, 1, 76, 94, 91, 23, 110, 12, 22, 104, 91, 18]
for i in range(42):
print(chr(b[i]^ord(a[i%16])),end="")

flag{59b8ed8f-af22-11e7-bb4a-3cf862d1ee75}

suctf-2016

serial-150

  • 静态分析

main函数(未去除混淆)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
.text:000000000040099C ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:000000000040099C public main
.text:000000000040099C main: ; DATA XREF: _start+1D↑o
.text:000000000040099C ; __unwind { // ___gxx_personality_v0
.text:000000000040099C push rbp
.text:000000000040099D mov rbp, rsp
.text:00000000004009A0 sub rsp, 200h
.text:00000000004009A7 lea rsi, [rbp-200h]
.text:00000000004009AE mov eax, 0
.text:00000000004009B3 mov edx, 20h
.text:00000000004009B8 mov rdi, rsi
.text:00000000004009BB mov rcx, rdx
.text:00000000004009BE rep stosq
.text:00000000004009C1 lea rsi, [rbp-100h]
.text:00000000004009C8 mov eax, 0
.text:00000000004009CD mov edx, 20h
.text:00000000004009D2 mov rdi, rsi
.text:00000000004009D5 mov rcx, rdx
.text:00000000004009D8 rep stosq
.text:00000000004009DB
.text:00000000004009DB loc_4009DB: ; CODE XREF: .text:00000000004009E1↓j
.text:00000000004009DB mov ax, 5EBh
.text:00000000004009DF xor eax, eax
.text:00000000004009E1 jz short near ptr loc_4009DB+2
.text:00000000004009E3 call near ptr 404DB6A6h
.text:00000000004009E8 add ds:_ZSt4cout@@GLIBCXX_3_4[rdi], bh
.text:00000000004009EE ; try {
.text:00000000004009EE call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const*)
.text:00000000004009F3
.text:00000000004009F3 loc_4009F3: ; CODE XREF: .text:00000000004009F9↓j
.text:00000000004009F3 mov ax, 5EBh
.text:00000000004009F7 xor eax, eax
.text:00000000004009F9 jz short near ptr loc_4009F3+2
.text:00000000004009FB call near ptr 0C59748h
.text:00000000004009FB ; ---------------------------------------------------------------------------
.text:0000000000400A00 dq 0C0BFC68948FFFFFEh, 0FFFFFE50E8006012h, 0FA74C03105EBB866h
.text:0000000000400A00 dq 0FFFFFE00858D48E8h, 0FFFFFE28E8C78948h, 0B8660E7410F88348h
.text:0000000000400A00 dq 0E9E8FA74C03105EBh, 85B60F0000023Fh, 660E74453CFFFFFEh
.text:0000000000400A00 dq 0E8FA74C03105EBB8h, 85B60F00000226E9h, 0FD0BE0FFFFFFE00h
.text:0000000000400A00 dq 0BE0FFFFFFE0F85B6h, 9B3DD001C0h, 0C03105EBB8660E74h
.text:0000000000400A00 dq 1FBE9E8FA74h, 3CFFFFFE0185B60Fh, 3105EBB8660E745Ah
.text:0000000000400A00 dq 1E2E9E8FA74C0h, 0FFFFFE0185B60F00h, 0FE0E85B60FD0BE0Fh
.text:0000000000400A00 dq 3DD001C0BE0FFFFFh, 0B8660E740000009Bh, 0E9E8FA74C03105EBh
.text:0000000000400A00 dq 285B60F000001B7h, 660E74393CFFFFFEh, 0E8FA74C03105EBB8h
.text:0000000000400A00 dq 85B60F0000019EE9h, 0FD0BE0FFFFFFE02h, 0BE0FFFFFFE0D85B6h
.text:0000000000400A00 dq 9B3DD001C0h, 0C03105EBB8660E74h, 173E9E8FA74h, 3CFFFFFE0385B60Fh
.text:0000000000400A00 dq 3105EBB8660E7464h, 15AE9E8FA74C0h, 0FFFFFE0385B60F00h
.text:0000000000400A00 dq 0FE0C85B60FD0BE0Fh, 3DD001C0BE0FFFFFh, 0B8660E740000009Bh
.text:0000000000400A00 dq 0E9E8FA74C03105EBh, 485B60F0000012Fh, 660E746D3CFFFFFEh
.text:0000000000400A00 dq 0E8FA74C03105EBB8h, 85B60F00000116E9h, 0FD0BE0FFFFFFE04h
.text:0000000000400A00 dq 0BE0FFFFFFE0B85B6h, 0B43DD001C0h, 0C03105EBB8660E74h
.text:0000000000400A00 dq 0EBE9E8FA74h, 3CFFFFFE0585B60Fh, 3105EBB8660E7471h
.text:0000000000400A00 dq 0D2E9E8FA74C0h, 0FFFFFE0585B60F00h, 0FE0A85B60FD0BE0Fh
.text:0000000000400A00 dq 3DD001C0BE0FFFFFh, 0B8660E74000000AAh, 0E9E8FA74C03105EBh
.text:0000000000400A00 dq 685B60F000000A7h, 660E74343CFFFFFEh, 0E8FA74C03105EBB8h
.text:0000000000400A00 dq 85B60F0000008EE9h, 0FD0BE0FFFFFFE06h, 0BE0FFFFFFE0985B6h
.text:0000000000400A00 dq 9B3DD001C0h, 0C03105EBB8660B74h, 85B60F66EBE8FA74h
.text:0000000000400A00 dq 0B74633CFFFFFE07h, 0FA74C03105EBB866h, 0FE0785B60F50EBE8h
.text:0000000000400A00 dq 85B60FD0BE0FFFFFh, 1C0BE0FFFFFFE08h, 0B740000009B3DD0h
.text:0000000000400A00 dq 0FA74C03105EBB866h, 3105EBB86628EBE8h, 400DC9BEE8FA74C0h
.text:0000000000400A00 dq 0D5E8006013E0BF00h, 3105EBB866FFFFFBh, 0B8E8FA74C0h
.text:0000000000400A00 dq 3105EBB86626EB00h, 400DE4BEE8FA74C0h, 0ADE8006013E0BF00h
.text:0000000000400A00 dq 3105EBB866FFFFFBh, 0B8E8FA74C0h
.text:0000000000400CA0 db 0, 0EBh, 8
.text:0000000000400CA3 ; ---------------------------------------------------------------------------
.text:0000000000400CA3 ; cleanup() // owned by 4009EE
.text:0000000000400CA3 mov rdi, rax
.text:0000000000400CA6 call __Unwind_Resume
.text:0000000000400CAB ; ---------------------------------------------------------------------------
.text:0000000000400CAB leave
.text:0000000000400CAC retn
.text:0000000000400CAC ; } // starts at 40099C

去除混淆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
.text:0000000000400A19                 lea     rax, [rbp-200h]
.text:0000000000400A20 mov rdi, rax
.text:0000000000400A23 call _strlen
.text:0000000000400A28 cmp rax, 16 ; 输入长度为16
.text:0000000000400A2C jz short loc_400A3C
.text:0000000000400A2E
.text:0000000000400A2E loc_400A2E: ; CODE XREF: .text:0000000000400A34↓j
.text:0000000000400A2E mov ax, 5EBh
.text:0000000000400A32 xor eax, eax
.text:0000000000400A34 jz short near ptr loc_400A2E+2
.text:0000000000400A34 ; ---------------------------------------------------------------------------
.text:0000000000400A36 db 0E8h
.text:0000000000400A37 ; ---------------------------------------------------------------------------
.text:0000000000400A37 jmp near ptr loc_400C7A+1
.text:0000000000400A3C ; ---------------------------------------------------------------------------
.text:0000000000400A3C
.text:0000000000400A3C loc_400A3C: ; CODE XREF: .text:0000000000400A2C↑j
.text:0000000000400A3C movzx eax, byte ptr [rbp-200h]
.text:0000000000400A43 cmp al, 'E' ; input[0]=E
.text:0000000000400A45 jz short loc_400A55
.text:0000000000400A45 ; ---------------------------------------------------------------------------
.text:0000000000400A47 db 66h ; f
.text:0000000000400A48 db 0B8h
.text:0000000000400A49 db 0EBh
.text:0000000000400A4A db 5
.text:0000000000400A4B db 31h ; 1
.text:0000000000400A4C db 0C0h
.text:0000000000400A4D db 74h ; t
.text:0000000000400A4E db 0FAh
.text:0000000000400A4F db 0E8h
.text:0000000000400A50 db 0E9h
.text:0000000000400A51 db 26h ; &
.text:0000000000400A52 db 2
.text:0000000000400A53 db 0
.text:0000000000400A54 db 0
.text:0000000000400A55 ; ---------------------------------------------------------------------------
.text:0000000000400A55
.text:0000000000400A55 loc_400A55: ; CODE XREF: .text:0000000000400A45↑j
.text:0000000000400A55 movzx eax, byte ptr [rbp-200h]
.text:0000000000400A5C movsx edx, al
.text:0000000000400A5F movzx eax, byte ptr [rbp-1F1h]
.text:0000000000400A66 movsx eax, al
.text:0000000000400A69 add eax, edx
.text:0000000000400A6B cmp eax, 9Bh ; input[0]+input[15]=0x9b
.text:0000000000400A70 jz short loc_400A80
.text:0000000000400A70 ; ---------------------------------------------------------------------------
.text:0000000000400A72 db 66h ; f
.text:0000000000400A73 db 0B8h
.text:0000000000400A74 db 0EBh
.text:0000000000400A75 db 5
.text:0000000000400A76 db 31h ; 1
.text:0000000000400A77 db 0C0h
.text:0000000000400A78 db 74h ; t
.text:0000000000400A79 db 0FAh
.text:0000000000400A7A db 0E8h
.text:0000000000400A7B db 0E9h
.text:0000000000400A7C db 0FBh
.text:0000000000400A7D db 1
.text:0000000000400A7E db 0
.text:0000000000400A7F db 0
.text:0000000000400A80 ; ---------------------------------------------------------------------------
.text:0000000000400A80
.text:0000000000400A80 loc_400A80: ; CODE XREF: .text:0000000000400A70↑j
.text:0000000000400A80 movzx eax, byte ptr [rbp-1FFh]
.text:0000000000400A87 cmp al, 'Z' ; input[1]=Z
.text:0000000000400A89 jz short loc_400A99
.text:0000000000400A89 ; ---------------------------------------------------------------------------
.text:0000000000400A8B db 66h ; f
.text:0000000000400A8C db 0B8h
.text:0000000000400A8D db 0EBh
.text:0000000000400A8E db 5
.text:0000000000400A8F db 31h ; 1
.text:0000000000400A90 db 0C0h
.text:0000000000400A91 db 74h ; t
.text:0000000000400A92 db 0FAh
.text:0000000000400A93 db 0E8h
.text:0000000000400A94 db 0E9h
.text:0000000000400A95 db 0E2h
.text:0000000000400A96 db 1
.text:0000000000400A97 db 0
.text:0000000000400A98 db 0
.text:0000000000400A99 ; ---------------------------------------------------------------------------
.text:0000000000400A99
.text:0000000000400A99 loc_400A99: ; CODE XREF: .text:0000000000400A89↑j
.text:0000000000400A99 movzx eax, byte ptr [rbp-1FFh]
.text:0000000000400AA0 movsx edx, al
.text:0000000000400AA3 movzx eax, byte ptr [rbp-1F2h]
.text:0000000000400AAA movsx eax, al
.text:0000000000400AAD add eax, edx
.text:0000000000400AAF cmp eax, 9Bh ; input[1]+input[14]=0x9b
.text:0000000000400AB4 jz short loc_400AC4
.text:0000000000400AB4 ; ---------------------------------------------------------------------------
.text:0000000000400AB6 db 66h ; f
.text:0000000000400AB7 db 0B8h
.text:0000000000400AB8 db 0EBh
.text:0000000000400AB9 db 5
.text:0000000000400ABA db 31h ; 1
.text:0000000000400ABB db 0C0h
.text:0000000000400ABC db 74h ; t
.text:0000000000400ABD db 0FAh
.text:0000000000400ABE db 0E8h
.text:0000000000400ABF db 0E9h
.text:0000000000400AC0 db 0B7h
.text:0000000000400AC1 db 1
.text:0000000000400AC2 db 0
.text:0000000000400AC3 db 0
.text:0000000000400AC4 ; ---------------------------------------------------------------------------
.text:0000000000400AC4
.text:0000000000400AC4 loc_400AC4: ; CODE XREF: .text:0000000000400AB4↑j
.text:0000000000400AC4 movzx eax, byte ptr [rbp-1FEh]
.text:0000000000400ACB cmp al, '9' ; input[2]=9
.text:0000000000400ACD jz short loc_400ADD
.text:0000000000400ACD ; ---------------------------------------------------------------------------
.text:0000000000400ACF db 66h ; f
.text:0000000000400AD0 db 0B8h
.text:0000000000400AD1 db 0EBh
.text:0000000000400AD2 db 5
.text:0000000000400AD3 db 31h ; 1
.text:0000000000400AD4 db 0C0h
.text:0000000000400AD5 db 74h ; t
.text:0000000000400AD6 db 0FAh
.text:0000000000400AD7 db 0E8h
.text:0000000000400AD8 db 0E9h
.text:0000000000400AD9 db 9Eh
.text:0000000000400ADA db 1
.text:0000000000400ADB db 0
.text:0000000000400ADC db 0
.text:0000000000400ADD ; ---------------------------------------------------------------------------
.text:0000000000400ADD
.text:0000000000400ADD loc_400ADD: ; CODE XREF: .text:0000000000400ACD↑j
.text:0000000000400ADD movzx eax, byte ptr [rbp-1FEh]
.text:0000000000400AE4 movsx edx, al
.text:0000000000400AE7 movzx eax, byte ptr [rbp-1F3h]
.text:0000000000400AEE movsx eax, al
.text:0000000000400AF1 add eax, edx
.text:0000000000400AF3 cmp eax, 9Bh ; input[2]+input[13]=0x9b
.text:0000000000400AF8 jz short loc_400B08
.text:0000000000400AF8 ; ---------------------------------------------------------------------------
.text:0000000000400AFA db 66h ; f
.text:0000000000400AFB db 0B8h
.text:0000000000400AFC db 0EBh
.text:0000000000400AFD db 5
.text:0000000000400AFE db 31h ; 1
.text:0000000000400AFF db 0C0h
.text:0000000000400B00 db 74h ; t
.text:0000000000400B01 db 0FAh
.text:0000000000400B02 db 0E8h
.text:0000000000400B03 db 0E9h
.text:0000000000400B04 db 73h ; s
.text:0000000000400B05 db 1
.text:0000000000400B06 db 0
.text:0000000000400B07 db 0
.text:0000000000400B08 ; ---------------------------------------------------------------------------
.text:0000000000400B08
.text:0000000000400B08 loc_400B08: ; CODE XREF: .text:0000000000400AF8↑j
.text:0000000000400B08 movzx eax, byte ptr [rbp-1FDh]
.text:0000000000400B0F cmp al, 'd' ; input[3]=d
.text:0000000000400B11 jz short loc_400B21
.text:0000000000400B11 ; ---------------------------------------------------------------------------
.text:0000000000400B13 db 66h ; f
.text:0000000000400B14 db 0B8h
.text:0000000000400B15 db 0EBh
.text:0000000000400B16 db 5
.text:0000000000400B17 db 31h ; 1
.text:0000000000400B18 db 0C0h
.text:0000000000400B19 db 74h ; t
.text:0000000000400B1A db 0FAh
.text:0000000000400B1B db 0E8h
.text:0000000000400B1C db 0E9h
.text:0000000000400B1D db 5Ah ; Z
.text:0000000000400B1E db 1
.text:0000000000400B1F db 0
.text:0000000000400B20 db 0
.text:0000000000400B21 ; ---------------------------------------------------------------------------
.text:0000000000400B21
.text:0000000000400B21 loc_400B21: ; CODE XREF: .text:0000000000400B11↑j
.text:0000000000400B21 movzx eax, byte ptr [rbp-1FDh]
.text:0000000000400B28 movsx edx, al
.text:0000000000400B2B movzx eax, byte ptr [rbp-1F4h]
.text:0000000000400B32 movsx eax, al
.text:0000000000400B35 add eax, edx
.text:0000000000400B37 cmp eax, 9Bh ; input[3]+input[12]=0x9b
.text:0000000000400B3C jz short loc_400B4C
.text:0000000000400B3C ; ---------------------------------------------------------------------------
.text:0000000000400B3E db 66h ; f
.text:0000000000400B3F db 0B8h
.text:0000000000400B40 db 0EBh
.text:0000000000400B41 db 5
.text:0000000000400B42 db 31h ; 1
.text:0000000000400B43 db 0C0h
.text:0000000000400B44 db 74h ; t
.text:0000000000400B45 db 0FAh
.text:0000000000400B46 db 0E8h
.text:0000000000400B47 db 0E9h
.text:0000000000400B48 db 2Fh ; /
.text:0000000000400B49 db 1
.text:0000000000400B4A db 0
.text:0000000000400B4B db 0
.text:0000000000400B4C ; ---------------------------------------------------------------------------
.text:0000000000400B4C
.text:0000000000400B4C loc_400B4C: ; CODE XREF: .text:0000000000400B3C↑j
.text:0000000000400B4C movzx eax, byte ptr [rbp-1FCh]
.text:0000000000400B53 cmp al, 'm' ; input[4]=m
.text:0000000000400B55 jz short loc_400B65
.text:0000000000400B57
.text:0000000000400B57 loc_400B57: ; CODE XREF: .text:0000000000400B5D↓j
.text:0000000000400B57 mov ax, 5EBh
.text:0000000000400B5B xor eax, eax
.text:0000000000400B5D jz short near ptr loc_400B57+2
.text:0000000000400B5D ; ---------------------------------------------------------------------------
.text:0000000000400B5F db 0E8h
.text:0000000000400B60 db 0E9h
.text:0000000000400B61 db 16h
.text:0000000000400B62 db 1
.text:0000000000400B63 db 0
.text:0000000000400B64 db 0
.text:0000000000400B65 ; ---------------------------------------------------------------------------
.text:0000000000400B65
.text:0000000000400B65 loc_400B65: ; CODE XREF: .text:0000000000400B55↑j
.text:0000000000400B65 movzx eax, byte ptr [rbp-1FCh]
.text:0000000000400B6C movsx edx, al
.text:0000000000400B6F movzx eax, byte ptr [rbp-1F5h]
.text:0000000000400B76 movsx eax, al
.text:0000000000400B79 add eax, edx
.text:0000000000400B7B cmp eax, 0B4h ; input[4]+input[11]=0xb4
.text:0000000000400B80 jz short loc_400B90
.text:0000000000400B80 ; ---------------------------------------------------------------------------
.text:0000000000400B82 db 66h ; f
.text:0000000000400B83 db 0B8h
.text:0000000000400B84 db 0EBh
.text:0000000000400B85 db 5
.text:0000000000400B86 db 31h ; 1
.text:0000000000400B87 db 0C0h
.text:0000000000400B88 db 74h ; t
.text:0000000000400B89 db 0FAh
.text:0000000000400B8A db 0E8h
.text:0000000000400B8B db 0E9h
.text:0000000000400B8C db 0EBh
.text:0000000000400B8D db 0
.text:0000000000400B8E db 0
.text:0000000000400B8F db 0
.text:0000000000400B90 ; ---------------------------------------------------------------------------
.text:0000000000400B90
.text:0000000000400B90 loc_400B90: ; CODE XREF: .text:0000000000400B80↑j
.text:0000000000400B90 movzx eax, byte ptr [rbp-1FBh]
.text:0000000000400B97 cmp al, 'q' ; input[5]=q
.text:0000000000400B99 jz short loc_400BA9
.text:0000000000400B99 ; ---------------------------------------------------------------------------
.text:0000000000400B9B db 66h ; f
.text:0000000000400B9C db 0B8h
.text:0000000000400B9D db 0EBh
.text:0000000000400B9E db 5
.text:0000000000400B9F db 31h ; 1
.text:0000000000400BA0 db 0C0h
.text:0000000000400BA1 db 74h ; t
.text:0000000000400BA2 db 0FAh
.text:0000000000400BA3 db 0E8h
.text:0000000000400BA4 db 0E9h
.text:0000000000400BA5 db 0D2h
.text:0000000000400BA6 db 0
.text:0000000000400BA7 db 0
.text:0000000000400BA8 db 0
.text:0000000000400BA9 ; ---------------------------------------------------------------------------
.text:0000000000400BA9
.text:0000000000400BA9 loc_400BA9: ; CODE XREF: .text:0000000000400B99↑j
.text:0000000000400BA9 movzx eax, byte ptr [rbp-1FBh]
.text:0000000000400BB0 movsx edx, al
.text:0000000000400BB3 movzx eax, byte ptr [rbp-1F6h]
.text:0000000000400BBA movsx eax, al
.text:0000000000400BBD add eax, edx
.text:0000000000400BBF cmp eax, 0AAh ; input[5]+input[10]=0xaa
.text:0000000000400BC4 jz short loc_400BD4
.text:0000000000400BC4 ; ---------------------------------------------------------------------------
.text:0000000000400BC6 db 66h ; f
.text:0000000000400BC7 db 0B8h
.text:0000000000400BC8 db 0EBh
.text:0000000000400BC9 db 5
.text:0000000000400BCA db 31h ; 1
.text:0000000000400BCB db 0C0h
.text:0000000000400BCC db 74h ; t
.text:0000000000400BCD db 0FAh
.text:0000000000400BCE db 0E8h
.text:0000000000400BCF db 0E9h
.text:0000000000400BD0 db 0A7h
.text:0000000000400BD1 db 0
.text:0000000000400BD2 db 0
.text:0000000000400BD3 db 0
.text:0000000000400BD4 ; ---------------------------------------------------------------------------
.text:0000000000400BD4
.text:0000000000400BD4 loc_400BD4: ; CODE XREF: .text:0000000000400BC4↑j
.text:0000000000400BD4 movzx eax, byte ptr [rbp-1FAh]
.text:0000000000400BDB cmp al, '4' ; input[6]=4
.text:0000000000400BDD jz short loc_400BED
.text:0000000000400BDD ; ---------------------------------------------------------------------------
.text:0000000000400BDF db 66h ; f
.text:0000000000400BE0 db 0B8h
.text:0000000000400BE1 db 0EBh
.text:0000000000400BE2 db 5
.text:0000000000400BE3 db 31h ; 1
.text:0000000000400BE4 db 0C0h
.text:0000000000400BE5 db 74h ; t
.text:0000000000400BE6 db 0FAh
.text:0000000000400BE7 db 0E8h
.text:0000000000400BE8 db 0E9h
.text:0000000000400BE9 db 8Eh
.text:0000000000400BEA db 0
.text:0000000000400BEB db 0
.text:0000000000400BEC db 0
.text:0000000000400BED ; ---------------------------------------------------------------------------
.text:0000000000400BED
.text:0000000000400BED loc_400BED: ; CODE XREF: .text:0000000000400BDD↑j
.text:0000000000400BED movzx eax, byte ptr [rbp-1FAh]
.text:0000000000400BF4 movsx edx, al
.text:0000000000400BF7 movzx eax, byte ptr [rbp-1F7h]
.text:0000000000400BFE movsx eax, al
.text:0000000000400C01 add eax, edx
.text:0000000000400C03 cmp eax, 9Bh ; input[6]+input[9]=0x9b
.text:0000000000400C08 jz short loc_400C15
.text:0000000000400C08 ; ---------------------------------------------------------------------------
.text:0000000000400C0A db 66h ; f
.text:0000000000400C0B db 0B8h
.text:0000000000400C0C db 0EBh
.text:0000000000400C0D db 5
.text:0000000000400C0E db 31h ; 1
.text:0000000000400C0F db 0C0h
.text:0000000000400C10 db 74h ; t
.text:0000000000400C11 db 0FAh
.text:0000000000400C12 db 0E8h
.text:0000000000400C13 db 0EBh
.text:0000000000400C14 db 66h ; f
.text:0000000000400C15 ; ---------------------------------------------------------------------------
.text:0000000000400C15
.text:0000000000400C15 loc_400C15: ; CODE XREF: .text:0000000000400C08↑j
.text:0000000000400C15 movzx eax, byte ptr [rbp-1F9h]
.text:0000000000400C1C cmp al, 'c' ; input[7]=c
.text:0000000000400C1E jz short loc_400C2B
.text:0000000000400C1E ; ---------------------------------------------------------------------------
.text:0000000000400C20 db 66h ; f
.text:0000000000400C21 db 0B8h
.text:0000000000400C22 db 0EBh
.text:0000000000400C23 db 5
.text:0000000000400C24 db 31h ; 1
.text:0000000000400C25 db 0C0h
.text:0000000000400C26 db 74h ; t
.text:0000000000400C27 db 0FAh
.text:0000000000400C28 db 0E8h
.text:0000000000400C29 db 0EBh
.text:0000000000400C2A db 50h ; P
.text:0000000000400C2B ; ---------------------------------------------------------------------------
.text:0000000000400C2B
.text:0000000000400C2B loc_400C2B: ; CODE XREF: .text:0000000000400C1E↑j
.text:0000000000400C2B movzx eax, byte ptr [rbp-1F9h]
.text:0000000000400C32 movsx edx, al
.text:0000000000400C35 movzx eax, byte ptr [rbp-1F8h]
.text:0000000000400C3C movsx eax, al
.text:0000000000400C3F add eax, edx
.text:0000000000400C41 cmp eax, 9Bh ; input[7]+input[8]=0x9b
.text:0000000000400C46 jz short loc_400C53

可提取的信息为

输入长度为16

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
input[0]=E
input[0]+input[15]=0x9b
input[1]=Z
input[1]+input[14]=0x9b
input[2]=9
input[2]+input[13]=0x9b
input[3]=d
input[3]+input[12]=0x9b
input[4]=m
input[4]+input[11]=0xb4
input[5]=q
input[5]+input[10]=0xaa
input[6]=4
input[6]+input[9]=0x9b
input[7]=c
input[7]+input[8]=0x9b

可得flag为EZ9dmq4c8g9G7bAV

  • 动态分析

输入的字符串被保存在[rbp-200h]

然后跳转到strlen进行长度比较(长度应为16)

1
2
3
4
5
6
.text:0000000000400A19 loc_400A19:                             ; CODE XREF: .text:0000000000400A12↑j
.text:0000000000400A19 lea rax, [rbp-200h]
.text:0000000000400A20 mov rdi, rax
.text:0000000000400A23 call _strlen
.text:0000000000400A28 cmp rax, 10h
.text:0000000000400A2C jz short near ptr loc_400A3B+1

判断第一个字符是否为E

1
2
3
.text:0000000000400A3C movzx   eax, byte ptr [rbp-200h]        ; CODE XREF: .text:0000000000400A2C↑j
.text:0000000000400A43 cmp al, 'E'
.text:0000000000400A45 jz short near ptr loc_400A54+1

手动对内存中的字符串进行修改,使其满足上述条件

第一个字符和最后一个字符相加等于0x9b,即最后一个字符为V

1
2
3
4
5
6
7
.text:0000000000400A55 movzx   eax, byte ptr [rbp-200h]        ; CODE XREF: .text:0000000000400A45↑j
.text:0000000000400A5C movsx edx, al
.text:0000000000400A5F movzx eax, byte ptr [rbp-1F1h]
.text:0000000000400A66 movsx eax, al
.text:0000000000400A69 add eax, edx
.text:0000000000400A6B cmp eax, 9Bh
.text:0000000000400A70 jz short near ptr loc_400A7F+1

不断重复以上步骤,最终得到flag

tinyctf-2014

elrond32

main
1
2
3
4
5
6
7
8
9
10
11
12
13
int __cdecl main(int a1, char **a2)
{
if ( a1 > 1 && sub_8048414(a2[1], 0) )
{
puts("Access granted");
sub_8048538((int)a2[1]);
}
else
{
puts("Access denied");
}
return 0;
}
sub_8048414
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
signed int __cdecl sub_8048414(_BYTE *a1, int a2)
{
signed int result; // eax

switch ( a2 )
{
case 0:
if ( *a1 == 'i' )
goto LABEL_19;
result = 0;
break;
case 1:
if ( *a1 == 'e' )
goto LABEL_19;
result = 0;
break;
case 3:
if ( *a1 == 'n' )
goto LABEL_19;
result = 0;
break;
case 4:
if ( *a1 == 'd' )
goto LABEL_19;
result = 0;
break;
case 5:
if ( *a1 == 'a' )
goto LABEL_19;
result = 0;
break;
case 6:
if ( *a1 == 'g' )
goto LABEL_19;
result = 0;
break;
case 7:
if ( *a1 == 's' )
goto LABEL_19;
result = 0;
break;
case 9:
if ( *a1 == 'r' )
LABEL_19:
result = sub_8048414(a1 + 1, 7 * (a2 + 1) % 11);
else
result = 0;
break;
default:
result = 1;
break;
}
return result;
}

可以得出,a1是一个字符串,sub_8048414读取字符串中的字符进行判断,直到result等于1,由此可以逆推出a1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
using namespace std;
void fun(int a){
if(a==0){
cout<<"i";
fun(7*(a+1)%11);
}
else if(a==1){
cout<<"e";
fun(7*(a+1)%11);
}
else if(a==3){
cout<<"n";
fun(7*(a+1)%11);
}
else if(a==4){
cout<<"d";
fun(7*(a+1)%11);
}
else if(a==5){
cout<<"a";
fun(7*(a+1)%11);
}
else if(a==6){
cout<<"g";
fun(7*(a+1)%11);
}
else if(a==7){
cout<<"s";
fun(7*(a+1)%11);
}
else if(a==9){
cout<<"r";
fun(7*(a+1)%11);
}
}
int main(){
fun(0);
return 0;
}

isengard

sub_8048538
1
2
3
4
5
6
7
8
9
10
int __cdecl sub_8048538(int a1)
{
int v2[33]; // [esp+18h] [ebp-A0h]
int i; // [esp+9Ch] [ebp-1Ch]

qmemcpy(v2, &unk_8048760, sizeof(v2));
for ( i = 0; i <= 32; ++i )
putchar(v2[i] ^ *(char *)(a1 + i % 8));
return putchar(10);
}

对a1字符串进行处理,得到flag

1
2
3
4
v2=[15, 31, 4, 9, 28, 18, 66, 9, 12, 68, 13, 7, 9, 6, 45, 55, 89, 30, 0, 89, 15, 8, 28, 35, 54, 7, 85, 2, 12, 8, 65, 10, 20]
a="isengard"
for i in range(33):
print(chr(v2[i]^ord(a[i%8])),end="")

flag{s0me7hing_S0me7hinG_t0lki3n}

也可以直接运行