魔法师的逆向之旅

1.revese2

一道简单的字符替换

2.内涵的软件

DBAPP{49d3c93df25caad81232130f3d2ebfad}

我还以为有什么加密,结果找半天没找着,直接将DBAPP改为flag就过了

3.新年快乐

打开一看内容很少,查壳,为upx壳

4.xor

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
int main(void)
{

​ char arry[] = {0x66,0xA,0x6B,0xC,0x77,0x26,0x4F,0x2E,0x40,0x11,0x78,0xD,0x5A,0x3B,0x55,0x11,0x70,0x19,0x46,0x1F,0x76,0x22,0x4D,0x23,0x44,0xE,0x67,0x6,0x68,0xF,0x47,0x32,0x4F,0x0};
​ //char arry[] = "f\nk\x0cw&O.@\x11x\rZ;U\x11p\x19F\x1fv\"M#D\x0eg\x06h\x0fG2O\x00";
​ for(int i = 32; i>=1; i--)
​ {
​ arry[i]^= arry[i-1];
​ }
​ printf("%s", arry);
​ return 0;
}

注意一下\x19F\x会匹配之后紧跟的16进制数直到第一个非16进制数,所以还是直接粘贴对应的16进制ascii码

5.reverse3

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=(base64)

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
#include<string.h>
int main(void)
{
char temp[] = "e3nifIH9b_C@n@dH";
for(int i = strlen(temp)-1; i>=0; i--)
{
temp[i] -=i;
}
printf("%s", temp);
}

之后cyberchef

6.helloword

简单的android逆向,正好最近也在学anroid逆向

直接去androidmainfest找清单文件,然后进入主程序

7.不一样的flag

确实不太一样,这道题看了wp才明白

1
2
3
4
puts("1 up");
puts("2 down");
puts("3 left");
printf("4 right\n:");

这种上下作于一看就是迷宫,这就去找迷宫为何

*(DWORD *)&11110100001010000101111[25]掌握上下

v4左右,一开始均置为0,掌左右为纵坐标

1

看这个判断的49这是’1’的ascii码,也就是1不可走,#结束

5 * *(DWORD *)&11110100001010000101111[25] - 41 + v4

这是5*纵坐标,这说明宽度为5,也刚好5乘5

*1111

01000

01010

00010

1111#

所以为222441144222就得到结束

8.SimpleRev

2

v11 = __readfsqword(0x28u):读取线程局部存储(TLS)中的金丝雀值(canary),用于检测栈溢出攻击。(有栈溢出,canary会修改)

这道题的关键是大小端序

text = join((const char *)key3, (const char *)s_);// “kills”
strcpy(key, key1); // “ADSFK”
进去看的data由于是字符串所以不存在端序问题,按d将其变为data后就会出现小端序

*(_QWORD *)src = ‘SLCDN’;

QWORD s[2]虽然输入的是字符串,但均转为8字节的数据,也均使用小端序存内存中是NDCL

text为密文(根据if ( !strcmp(text, str2) )
puts(“Congratulation!\n”);)

text是killshadow

密钥为ADSFKNDCL

1
2
3
4
5
6
for ( i = 0; i < v7; ++i )
{
if ( key[v5 % v7] > 64 && key[v5 % v7] <= 90 )
key[i] = key[v5 % v7] + 32;
++v5;
}

这一看就是就是大小写转换

1
2
3
4
5
6
7
8
9
10
11
12
13
if ( char <= 96 || char > 'z' )
{
if ( char > '@' && char <= 'Z' )
{
str2[v4] = (char - 39 - key[v5 % i_1] + 97) % 26 + 97;
++v5;
}
}
else
{
str2[v4] = (char - 39 - key[v5 % i_1] + 97) % 26 + 97;
++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
#include<stdio.h>
#include<string.h>
#define base58_size 58
int main(void)
{
char arry[] = "killshadow";
char key[] = "adsfkndcls";
int temp;
for(int i = 0; i<strlen(arry); i++)
{
temp = arry[i] - 97;
printf("%d ", temp);
}
printf("\n");
for(int i = 0; i<strlen(key); i++)
{
temp = -key[i] + 97 - 39;
printf("%d ", temp);
}
return 0;
}
#include<stdio.h>
int main(void)
{
int arry[] = {10 ,8 ,11 ,11 ,18 ,7 ,0 ,3 ,14 ,22 };
int temp[] = {-39, -42, -57, -44, -49, -52, -42, -41, -50, -57};
for(int i = 0; i<10; i++)
{
for(char num = 'A'; num<='Z'; num++)
{
if(arry[i] == (num+temp[i])%26)
{
printf("%c", num);

}
}

}
}

stract函数仅是关心内存中存的值,其他的并不关心

查看小端序方法

(1)deteceasy中LE小端序,BE大端序

(2)将数值赋给字符串

(3

  temp(void)
  {int num = 1;
   return (*(char*)&num == 1); // 1为小端序,0为大端序
    }

(4)小端序:x86/AMD64 架构(Windows/Linux)、ARM 架构

​ 大端序:网络协议、Java 字节码、部分嵌入式系统(如 PowerPC)PNG 为大端序

9.[GXYCTF2019]luck_guy1

程序有个伪随机数生成,所以有固定顺序

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
#include<string.h>
#include<tsdio.h>
int main(void)

{

char arry[] = {0x69, 0x63, 0x75, 0x67, 0x60, 0x6F, 0x66, 0x7F};

for(int i = 0; i<=7; i++)

{

if(i%2==1)

arry[i] -= 2;

else

arry[i]--;

}

for(int i = 0; i<=7; i++)

printf("%c", arry[i]);

}

得到hate_me}

10.Java逆向解密1

注意的是^优先级低于-