壳的分类

image-20220224201113558

刷题记录

新年快乐

首先用PEiD查看其大小 是32位 又发现加了壳UPX

image-20220225115351925

在od中打开,脱壳要先找到oep,由于现在的脱壳水平十分菜鸡,于是就一个个f8先运行

把一些死循环跳过,经过漫长的努力后发现了popad

image-20220225120120213

继续f8,跳过jnz死循环,最后进入程序(找到oep)

右键dump一下

image-20220225120445721

dump过后再用ida32打开dump过后的程序

此时已经出现的原有函数,f5查看c伪代码,最终得到flag

flag{HappyNewYear!}

image-20220225120521773

xor

首先判断一下,是64位的,然后丢到idapro64打开

image-20220225140005321

image-20220225140059968

按f5查看伪代码

image-20220225140125770

hello world

apk文件,Android逆向,用Androidkiller打开,找到flag

image-20220225150334494

reserve 3

查壳后发现无壳,是32位的,用ida打开,shift+f12查看

发现right flag,双击进入

image-20220226003453711

image-20220226172230701

选中aRightFlag,按ctrl+x,再按f5查看伪代码image-20220226003546501

分析伪代码得知重点在Str2和Destination上,同时从sub_4110BE可以看出这里进行了函数加密,双击sub_4110BE

image-20220226003736734

双击aAbcdefghijklmn,进入后发现’ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=’

这肯定是base64加密了

image-20220226003840374

再次分析伪代码,得知flag经过for循环,每次都加了j,查看Str2的值

image-20220226172744006

那么要做的就很简单了。首先将字符串数组Str2每个减去i,再用得到的结果进行base64解密,由于本人是菜鸡,只能用在线解密,最后得到flag

image-20220226015620127

image-20220226174151735

不一样的flag

老规矩,查壳,查位

image-20220226193139453

无壳,32位

本想常识一下动态分析,发现啥都不会,就会运行到那

image-20220226193200833

发现了一个奇怪的字符串,但是不知道是干嘛的

image-20220226193328755

用ida打开

在main函数中使用f5大法

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
__main();
v4 = 0;
strcpy(v3, "*11110100001010000101111#");
while ( 1 )
{
puts("you can choose one action to execute");
puts("1 up"); //上
puts("2 down"); //下
puts("3 left"); //左
printf("4 right\n:"); //右
scanf("%d", &v5);
if ( v5 == 2 )
{
++*(_DWORD *)&v3[25];
}
else if ( v5 > 2 )
{
if ( v5 == 3 )
{
--v4;
}
else
{
if ( v5 != 4 )
LABEL_13:
exit(1);
++v4;
}
}
else
{
if ( v5 != 1 )
goto LABEL_13;
--*(_DWORD *)&v3[25];
}
for ( i = 0; i <= 1; ++i )
{
if ( *(int *)&v3[4 * i + 25] < 0 || *(int *)&v3[4 * i + 25] > 4 )
exit(1);
}
if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 49 )
exit(1);
if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 35 )
{
puts("\nok, the order you enter is the flag!");
exit(0);
}
}
}

上下左右,考虑迷宫,那么就要寻找地图了

image-20220226193858938

#是出口,所以之前发现的那个奇怪的字符串应该就是地图,地图不可能是一串,得是个形状,再考虑图中25的情况,那么应该是将那串字符变成5*5的形式

image-20220226194026087

1
2
3
4
5
"*1111"
"01000"
"01010"
"00010"
"1111#

那就是下下下右右上上上右右下下下 2224411144222

测试flag是否正确,正确

[ACTF新生赛2020]easyre

image-20220227000303373

image-20220227004652338

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 v4[12]; // [esp+12h] [ebp-2Eh] BYREF
int v5[3]; // [esp+1Eh] [ebp-22h]
char v6[5]; // [esp+2Ah] [ebp-16h] BYREF
int v7; // [esp+2Fh] [ebp-11h]
int v8; // [esp+33h] [ebp-Dh]
int v9; // [esp+37h] [ebp-9h]
char v10; // [esp+3Bh] [ebp-5h]
int i; // [esp+3Ch] [ebp-4h]

__main();
qmemcpy(v4, "*F'\"N,\"(I?+@", sizeof(v4));
printf("Please input:");
scanf("%s", v6);
if ( v6[0] != 65 || v6[1] != 67 || v6[2] != 84 || v6[3] != 70 || v6[4] != 123 || v10 != 125 )
return 0;
v5[0] = v7;
v5[1] = v8;
v5[2] = v9;
for ( i = 0; i <= 11; ++i )
{
if ( v4[i] != _data_start__[*((char *)v5 + i) - 1] )
return 0;
}
printf("You are correct!");
return 0;

image-20220227004905173

image-20220227004930374

看懂了大概,应该是要用_data_Start_于v4比较,但是if那段看不懂要干嘛,先暂时放弃….

XCTF 新手区

game

打开文件,游戏意思大概是要我们把灯全部点亮后就可以得到flag

查壳后发现无壳

拖入od中进行调试,查找下有无flag的字符串

image-20220302142017789

发现真有,跟进一下,发现他的位置在程序入口点的上方,这里我先下了个断点,但是禁用了

image-20220302142046951

然后重载程序,在call指令且1程序有运行出结果画面的地方做好标记

image-20220302141914161

试了很久之后发现,这个call最后总会跳转到一个地方使输入页面重新出现,那于是就想可以直接跳转到 done!flag那里,双击进行位置更改,成功得到flag!

image-20220302142133596

image-20220302141854603

调试过程:本来想到要用call直接跳转的时候就开始尝试了,在前几个call那里跳转总是会出来乱码

image-20220302142443025

直到到这个call才成功

image-20220302142503363

Hello ctf

拿到题目后查壳,无壳,32位

打开IDA,f5查看伪代码

image-20220313113806597

分析代码:大致意思是先将字符串复制到x13中,然后输入字符串v9,v9长度不能大于17,然后仔细观察v13,正好34个长度,那么可以猜想v13应该是由17个16进制位组成的,继续分析,for循环中遍历v9,并将每一个下标所包含的数复制给v4,之后再sprintf中将v4数据格式化给Buffer,并且连接v10和Buffer,最后将v13和v10进行比较,相同则输出成功,在前面的memset函数中,已经将v10的值变为0,所以我们只要将v13进行16进制转换字符即可得到flag

image-20220313114827205

BUU simplerev

拿到题目有点懵,无后缀,加exe后程序也不能运行,拖入ida32

image-20220303164353496

提示要用64位打开,打开后查看伪代码

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
unsigned __int64 Decry()
{
char v1; // [rsp+Fh] [rbp-51h]
int v2; // [rsp+10h] [rbp-50h]
int v3; // [rsp+14h] [rbp-4Ch]
int i; // [rsp+18h] [rbp-48h]
int v5; // [rsp+1Ch] [rbp-44h]
char src[8]; // [rsp+20h] [rbp-40h] BYREF
__int64 v7; // [rsp+28h] [rbp-38h]
int v8; // [rsp+30h] [rbp-30h]
__int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
int v10; // [rsp+50h] [rbp-10h]
unsigned __int64 v11; // [rsp+58h] [rbp-8h]

v11 = __readfsqword(0x28u);
*(_QWORD *)src = 'SLCDN';
v7 = 0LL;
v8 = 0;
v9[0] = 'wodah';
v9[1] = '\0';
v10 = 0;
text = (char *)join(key3, v9); //连接字符串test[]=killshadow
strcpy(key, key1);//将key1的值复制到key中,key[]=ADSFK
strcat(key, src);//连接sey和scr,key[]=ADSFKNDCLA,长度为10
v2 = 0;
v3 = 0;
getchar();
v5 = strlen(key);//v5=10
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > '@' && key[v3 % v5] <= 'Z' )
key[i] = key[v3 % v5] + 32;
++v3;
}//将key中的字符大写改小写,此时v3=10,key[]=adsfkndcls
printf("Please input your flag:");
while ( 1 )
{
v1 = getchar();
if ( v1 == '\n' )
break;
if ( v1 == ' ' )
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 122 )//如果v1中的字符不为小写
{
if ( v1 > 64 && v1 <= 9 )//如果v1中的字符为大写字母
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}/
}
else
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) )
puts("Congratulation!\n");
else
puts("Try again!\n");
return __readfsqword(0x28u) ^ v11;
}

image-20220303171236192

image-20220303171251053

image-20220303171903837

上脚本

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
#include <iostream> 
#include <iomanip>
using namespace std;

int main()
{
char key[] = "adsfkndcls";
char text[] = "killshadow";
int v3 = 10, v5 = 10;

for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 128; j++)
{
if (j <= 'A' || j > 'z' || j > 'Z' && j <= 'a')
{
continue;
}
if ((j - 39 - key[v3 % v5] + 97) % 26 + 97 == text[i])
{
cout << char(j);
++v3;
break;
}

}
}
return 0;
}

image-20220320110623254

简单注册器

image-20220320112815037

改用JEB打开

image-20220527180609604

找到反编译代码

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
public void onClick(View arg13) {
int v11 = 0x1F;
int v9 = 2;
int v2 = 1;
String v6 = this.val$editview.getText().toString();
if(v6.length() != 0x20 || v6.charAt(v11) != 97 || v6.charAt(1) != 98 || v6.charAt(0) + v6.charAt(v9) - 0x30 != 56) {
v2 = 0;
}

if(v2 == 1) {
char[] v5 = "dd2940c04462b4dd7c450528835cca15".toCharArray();
v5[v9] = ((char)(v5[v9] + v5[3] - 50));
v5[4] = ((char)(v5[v9] + v5[5] - 0x30));
v5[30] = ((char)(v5[v11] + v5[9] - 0x30));
v5[14] = ((char)(v5[27] + v5[28] - 97));
int v4;
for(v4 = 0; v4 < 16; ++v4) {
char v0 = v5[0x1F - v4];
v5[0x1F - v4] = v5[v4];
v5[v4] = v0;
}

this.val$textview.setText("flag{" + String.valueOf(v5) + "}");
}
else {
this.val$textview.setText("输入注册码错误");
}
}
});
}

稍微修改一下即可得到脚本

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
#include<iostream>
#include<iomanip>
#include<math.h>
#include<cmath>
using namespace std;
int main()
{
int v11 = 0x1F;
int v9 = 2;
int v2 = 1;
if (v2 == 1) {
char v5[] = "dd2940c04462b4dd7c450528835cca15";
v5[v9] = ((char)(v5[v9] + v5[3] - 50));
v5[4] = ((char)(v5[v9] + v5[5] - 0x30));
v5[30] = ((char)(v5[v11] + v5[9] - 0x30));
v5[14] = ((char)(v5[27] + v5[28] - 97));
int v4;
for (v4 = 0; v4 < 16; ++v4) {
char v0 = v5[0x1F - v4];
v5[0x1F - v4] = v5[v4];
v5[v4] = v0;
}

for (int i = 0; i < 33; i++)
{
cout << v5[i];
}

return 0;
}
}

flag{59acc538825054c7de4b26440c0999dd}

刮开有奖

查壳 无壳 32位

image-20220327004046590

猜测应该是base64,跟进

image-20220327004315980

ctrl+x,f5查看伪代码

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
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7[2]; // [esp+8h] [ebp-20030h] BYREF
int v8; // [esp+10h] [ebp-20028h]
int v9; // [esp+14h] [ebp-20024h]
int v10; // [esp+18h] [ebp-20020h]
int v11; // [esp+1Ch] [ebp-2001Ch]
int v12; // [esp+20h] [ebp-20018h]
int v13; // [esp+24h] [ebp-20014h]
int v14; // [esp+28h] [ebp-20010h]
int v15; // [esp+2Ch] [ebp-2000Ch]
int v16; // [esp+30h] [ebp-20008h]
CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 == 1001 )
{
memset(String, 0, 0xFFFFu);//将string初始化为0
GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
if ( strlen(String) == 8 )
{
v7[0] = 90;
v7[1] = 74;
v8 = 83;
v9 = 69;
v10 = 67;
v11 = 97;
v12 = 78;
v13 = 72;
v14 = 51;
v15 = 110;
v16 = 103;
sub_4010F0(v7, 0, 10);
memset(v18, 0, 0xFFFFu);
v18[0] = String[5];
v18[2] = String[7];
v18[1] = String[6];
v4 = (const char *)sub_401000(v18, strlen(v18));
memset(v18, 0, 0xFFFFu);
v18[1] = String[3];
v18[0] = String[2];
v18[2] = String[4];
v5 = (const char *)sub_401000(v18, strlen(v18));
if ( String[0] == v7[0] + 34
&& String[1] == v10
&& 4 * String[2] - 141 == 3 * v8
&& String[3] / 4 == 2 * (v13 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
return 0;
EndDialog(hDlg, (unsigned __int16)a3);
return 1;
}

跟进一下sub_4010F0

image-20220327130141712

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
int __cdecl sub_4010F0(int a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx

result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = 4 * i;
v6 = *(_DWORD *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(_DWORD *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(_DWORD *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(_DWORD *)(a1 + 4 * result) = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}

实在看不懂,试了一下用编译器运行,但是直接报错,所以在网上寻找答案时发现了一个非常适合新手的wp

(42条消息) BUUCTF 刮开有奖(特别详细了,尽自己全力理解所写)_别害怕我在的博客-CSDN博客_buuctf 刮开有奖

image-20220327134308613

看到这里真的是恍然大悟

修改sub_4010F0函数后运行

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
#include <iostream> 
#include <cmath>
using namespace std;
int __cdecl sub_4010F0(char* a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx

result = a3;
for (i = a2; i <= a3; a2 = i)
{
v5 = i;
v6 = a1[i];
if (a2 < result && i < result)
{
do
{
if (v6 > a1[result])
{
if (i >= result)
break;
++i;
a1[v5] = a1[result];
if (i >= result)
break;
while (a1[i] <= v6)
{
if (++i >= result)
goto LABEL_13;
}
if (i >= result)
break;
v5 = i;
a1[result] = a1[i];
}
--result;
} while (i < result);
}
LABEL_13:
a1[result] = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}
int main()
{
char str[15] = { 90,74,83,69,67,97,78,72,51,110,103 };
sub_4010F0(str, 0, 10);
for (int i = 0; i < 11; i++)
{
cout << str[i];
}
return 0;
}

image-20220327134459451

sub_4010F0函数是对v7-v16字符串的加密

image-20220410131343835

跟进一下

image-20220410131414966

发现数据byte_407830,继续跟进

image-20220410131515759

估计就是base64加密,对v4,v5进行base64加密,在网上进行在线解密

v4 = jMp,v5 = WP1,分析最后的if语句

1
2
3
4
5
6
7
8
9
if ( String[0] == v7[0] + 34  //v7[0]==3
&& String[1] == v10 //v10==J,即之前使用sub_4010F0函数进行加密出来的字符
&& 4 * String[2] - 141 == 3 * v8 //string[2]==(3*v8+141)/4
&& String[3] / 4 == 2 * (v13 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}

最后组合前几个UJWP,再将v4v5跟其进行组合

得到flag flag{UJWP1jMp}

[ACTF新生赛2020]rome

查壳,无壳,32位

image-20220410133055183

shift+f12查看字符串

image-20220410133145244

进入到”You are correct!”中

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
int func()
{
int result; // eax
int v1[4]; // [esp+14h] [ebp-44h]
unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
unsigned __int8 v3; // [esp+25h] [ebp-33h]
unsigned __int8 v4; // [esp+26h] [ebp-32h]
unsigned __int8 v5; // [esp+27h] [ebp-31h]
unsigned __int8 v6; // [esp+28h] [ebp-30h]
int v7; // [esp+29h] [ebp-2Fh]
int v8; // [esp+2Dh] [ebp-2Bh]
int v9; // [esp+31h] [ebp-27h]
int v10; // [esp+35h] [ebp-23h]
unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF

strcpy(v12, "Qsw3sj_lz4_Ujw@l"); //将字符copy到v12中
printf("Please input:");
scanf("%s", &v2);
result = v2;
if ( v2 == 65 )
{
result = v3;
if ( v3 == 67 )
{
result = v4;
if ( v4 == 84 )
{
result = v5;
if ( v5 == 70 )
{
result = v6;
if ( v6 == 123 )
{
result = v11;
if ( v11 == 125 )
{
v1[0] = v7;
v1[1] = v8;
v1[2] = v9;
v1[3] = v10;
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )//如果是大写 *(_DWORD *)&v12[17])==0
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )//小写
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
++*(_DWORD *)&v12[17];
}
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];//result==v12[0]直到result==v12[15]
if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )
return result;//如果经过加密后的字符==result
++*(_DWORD *)&v12[17];
}
result = printf("You are correct!");
}
}
}
}
}
}
return result;
}

2022DASCTF Apr X FATE 防疫挑战赛

re 奇怪的交易

拿到题目,文件无后缀,拖入ida64,shift+f12查看字符串

image-20220423110750497

猜测可能是upx的壳,用记事本打开,发现是ELF文件,

image-20220423111128810

本来想用vs打开看看,发现不行

image-20220423111203709

适合破解新手的160个CrackMe

–001

查壳后发现无壳,拖入od调试

查找字符串

image-20220316102047748

image-20220316102101404

发现有ASCII “Sorry , The serial is incorect !”和ASCII “God Job dude !! =)”

image-20220316103635657

双击进入0042FA63

image-20220316102419200

在0042FA5A处有跳转,由于应该要跳过Try Again和Sorry….,所以把这里修改为jmp

image-20220316103719319

再进入0042FB0C

这里应该要运行到此处,所以将0042FB03 nop掉,最后运行程序,成功!

image-20220316101929107

接着破解serial

查找字符串Try Again,并在每一个Try Again下断点

image-20220316105621744

接着发现有个数据的”Try Again!!”,同时发现疑似破解serial的关键 “Hello Dude!”

image-20220316105910843

image-20220316105859154

最后还有一个

image-20220316110337695

下好断点后运行程序,向上查找

image-20220316110721417

将0042F4D5处nop掉,因为这样就不会跳转到Failed,再次运行程序

image-20220316111102851

rsa加密

参考blog(85条消息) 带你彻底理解RSA算法原理_小宝一号的博客-CSDN博客_rsa算法