RCTF
三题

LoongArch

https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN

考察新语言的学习

结合文档看明白了逻辑

大概是这样的,输出为esp+32到esp+96的内容

而要做的是反推出esp+0到esp+32的内容

一步一步往上推即可

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
#include <stdio.h>

unsigned long long revd(unsigned long long num)
{
char org[64] = {};
for(int i = 0; i < 64; ++i)
{
unsigned long long mask = 1;
mask <<= i;
org[i] = (num & mask) >> i;
}
unsigned long long result = 0;
for(int i = 0; i < 64; ++i)
{
result |= ((unsigned long long)(org[i]) << (63 - i));
}
return result;
}

unsigned long long rev8B(unsigned long long num)
{
unsigned long long result = 0;
for(int i = 0; i < 8; ++i)
{
unsigned long long tmp = (num & ((unsigned long long)0xff << (8 * i))) >> (8 * i);
char org[8] = {};
for(int j = 0; j < 8; ++j)
{
org[j] = (tmp & (1 << j)) >> j;
}
tmp = 0;
for(int j = 0; j < 8; ++j)
{
tmp |= ((unsigned long long)(org[j]) << (7 - j));
}
result |= (tmp << (8 * i));
}
return result;
}

unsigned long long makemask(int count)
{
unsigned long long result = 0;
for(int i = 0; i < count; ++i)
{
result |= 0xff << (i * 8);
}
return result;
}

unsigned long long repick(unsigned long long left, unsigned long long right,int count)
{
return ((left & makemask(count)) << 8 * (8 - count)) | (right >> 8 * count);
//bytepick.d t0,t6,t5,3
//bytepick.d rd,rj,rk,sa3
//rd = {rk[8*(8-sa3):0],rj[63:8*(8-sa3)]}
//rd = {rk[40:0],rj[63:40]}
//t0 = {t5[40:0],t6[63:40]}
//t1 = {t7[40:0],t4[63:40]}
//t2 = {t4[40:0],t5[63:40]}
//t3 = {t6[40:0],t7[63:40]}
}

int main()
{
unsigned long long
sp32=0x8205f3d105b3059d,
sp40=0xa89aceb3093349f3,
sp48=0xd53db5adbcabb984,
sp56=0x39cea0bfd9d2c2d4,
sp64=0xc513455508290500,
sp72=0x006d621abb30b918,
sp80=0xbc555b9f4c6f86a1,
sp88=0x050d78ad181a626d;

unsigned long long
t0 = 0,
t1 = 0,
t2 = 0,
t3 = 0,
t4 = 0,
t5 = 0,
t6 = 0,
t7 = 0;

t0 = t1 = t2 = t3 = ~0;
t4 = sp64 ^ t0;
t5 = sp72 ^ t1;
t6 = sp80 ^ t2;
t7 = sp88 ^ t3;

t0 = rev8B(t4);
t1 = rev8B(t5);
t2 = rev8B(t6);
t3 = rev8B(t7);

t4 = repick(t1,t2,3);
t5 = repick(t2,t0,3);
t6 = repick(t0,t3,3);
t7 = repick(t3,t1,3);

t0 = revd(t4);
t1 = revd(t5);
t2 = revd(t6);
t3 = revd(t7);

t4 = sp32;
t5 = sp40;
t6 = sp48;
t7 = sp56;

t0 ^= t4;
t1 ^= t5;
t2 ^= t6;
t3 ^= t7;

printf("%.8s%.8s%.8s%.8s",(char*)&t0,(char*)&t1,(char*)&t2,(char*)&t3);
return 0;
}

RCTF{We1c0m3_t0_RCTF_2o21_@&-=+}

Hi!Harmony!

使用ghidra反编译即可

贴一下反编译代码

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
void UndefinedFunction_8000095c(void)
{
int iStack84;
undefined4 uStack72;
undefined4 uStack68;
undefined4 uStack64;
undefined4 uStack60;
undefined4 uStack56;
undefined2 uStack52;
undefined uStack50;
undefined uStack49;
undefined4 uStack48;
undefined4 uStack44;
undefined4 uStack40;
undefined4 uStack36;
undefined4 uStack32;
undefined4 uStack28;
undefined2 uStack24;

do {
FUN_80000832("Welcome to RCTF 2021...\n\r");
uStack72 = 0x4d524148;
uStack68 = 0x44594e4f;
uStack64 = 0x4d414552;
uStack60 = 0x4f505449;
uStack56 = 0x42495353;
uStack52 = 0x454c;
uStack50 = 0;
uStack48 = 0x44434241;
uStack44 = 0x48474645;
uStack40 = 0x4c4b4a49;
uStack36 = 0x504f4e4d;
uStack32 = 0x54535251;
uStack28 = 0x58575655;
uStack24 = 0x5a59;
iStack84 = 0;
while (iStack84 < 0x16) {
if (*(char *)((int)&uStack72 + iStack84) + 3 < 0x5b) {
*(char *)((int)&uStack72 + iStack84) = *(char *)((int)&uStack72 + iStack84) + '\x03';
}
else {
*(undefined *)((int)&uStack72 + iStack84) =
(&uStack49)[(*(char *)((int)&uStack72 + iStack84) + -0x57) % 0x1a];
}
iStack84 = iStack84 + 1;
}
FUN_80000832("The result of encryption: %s\n\r",&uStack72);
FUN_800059a2(1000);
} while( true );
}

虽然看上去很怪,连输入都没有

不过跟着他走一下,得到一个字符串,包上RCTF{}提交对了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
char uStack72[] ="HARMONYDREAMITPOSSIBLE";

char uStack48[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

for(int i = 0; uStack72[i]; ++i)
{
if (uStack72[i] < 0x58)
{
uStack72[i] += 3;
}
else
{
uStack72[i] =uStack48[((uStack72[i] - 0x57) % 0x1a) - 1];
}
}
printf("%s",uStack72);
}

RCTF{KDUPRQBGUHDPLWSRVVLEOH}

Valgrind

分析文件前面的几百行 大概有这么些内容

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
0x8048464 sub   esp, 0x54
0x8048467 call 0x080485f1


0x80485f1 pop eax
0x80485f4 ret

0x804846c lea eax,[eax+0x1b94]
0x8048471
0x8048477 sub ebp, 0xC
0x804847a xor eax,eax
0x804847c mov [ebp-0x32],0x656d3174
0x8048483 mov [ebp-0x2E],0x7530795f
0x804848a mov [ebp-0x2A],0x6a6e655f
0x8048491 mov [ebp-0x26],0x775f7930
0x8048498 mov [ebp-0x22],0x31743561
0x804849f mov [ebp-0x1E],0x775f676e
0x80484a6 mov [ebp-0x1A],0x6e5f3561
0x80484ad mov [ebp-0x16],0x775f746f
0x80484b4 mov [ebp-0x12],0x65743561
0x80484bb mov [ebp-0x0E],0x0064
0x80484c1 mov [ebp-0x54],0x00000003
0x80484c8 mov [ebp-0x4C],0x41
0x80484cc mov [ebp-0x4B],0x42
0x80484d0 mov [ebp-0x4A],0x43
0x80484d4 mov [ebp-0x49],0x44
0x80484d8 mov [ebp-0x48],0x45
0x80484dc mov [ebp-0x47],0x46
0x80484e0 mov [ebp-0x46],0x47
0x80484e4 mov [ebp-0x45],0x48
0x80484e8 mov [ebp-0x44],0x49
0x80484ec mov [ebp-0x43],0x4a
0x80484f0 mov [ebp-0x42],0x4b
0x80484f4 mov [ebp-0x41],0x4c
0x80484f8 mov [ebp-0x40],0x4d
0x80484fc mov [ebp-0x3F],0x4e
0x8048500 mov [ebp-0x3E],0x4f
0x8048504 mov [ebp-0x3D],0x50
0x8048508 mov [ebp-0x3C],0x51
0x804850C mov [ebp-0x3B],0x52
0x8048510 mov [ebp-0x3A],0x53
0x8048514 mov [ebp-0x39],0x54
0x8048518 mov [ebp-0x38],0x55
0x804851C mov [ebp-0x37],0x56
0x8048520 mov [ebp-0x36],0x57
0x8048524 mov [ebp-0x35],0x58
0x8048528 mov [ebp-0x34],0x59
0x804852C mov [ebp-0x33],0x5a
0x8048530 mov [ebp-0x58],0x00000000
0x8048537 jmp 0x080485c8
0x804853c lea eax,[ebp-0x32]
0x804853f mov ebx,[ebp-0x58]
0x8048542 add eax,ebx
0x8048544 mov al,[eax] //取一位
0x8048547 mov edx,al
0x804854a mov eax,[ebp-0x54]
0x804854d add eax,edx //加3
0x804854f cmp eax,0x0000005a //与'Z'相比
0x8048552 jna 0x8048574
0x8048554 lea eax,[ebp-0x32] //若小于'Z'
0x8048557 mov ebx,[ebp-0x58]
0x804855a add eax,ebx
0x804855c mov al,[eax] //取这位
0x804855f mov eax,al
0x8048561 mov ebx,[ebp-0x54]
0x8048564 add eax,ebx //加上三
0x8048566 mov ecx,eax
0x8048568 lea eax,[ebp-0x32]
0x804856b lea edx,[ebp-0x58]
0x804856e add eax,edx
0x8048570 mov [eax],cl //写回
0x8048572 jmp 0x080485c4
0x8048574 lea eax,[ebp-0x32] //若大于'Z'
0x8048577 mov ebx,[ebp-0x58]
0x804857a add eax,ebx
0x804857c mov al,[eax] //取一位
0x804857f mov eax,al
0x8048582 mov ebx,[ebp-0x54]
0x8048585 add eax,ebx //加三
0x8048587 sub eax,0x5A //减'Z'
0x804858a mov ecx,eax ///
0x804858f mov ebx,eax ///
0x8048591 mul eax,0x4ec4ec4f ///
0x8048593 sar eax,0x03 ///
0x8048596 nop ///
0x8048598 sar ebx,0x1f ///
0x804859b sub eax,ebx ///这一段像是做取余
0x804859d nop ///
0x804859f mov [ebp-0x50],eax ///因为后面的数组是26位字母
0x80485a2 mov eax,[ebp-0x50] ///盲猜取余26
0x80485a5 mul eax,0x1a ///
0x80485a8 sub ecx,eax ///
0x80485aa nop ///
0x80485ac mov [ebp-0x50],ecx ///
0x80485af mov ecx,[ebp-0x50] ///
0x80485b2 sub ecx,0x00000001 //取余结果减1
0x80485b5 mov al,[ebp+ecx-0x4C] //从数组中取一个char
0x80485ba lea ecx,[ebp-0x32]
0x80485bd mov edx,[ebp-0x58]
0x80485c0 add edx,ecx
0x80485c2 mov [edx],al //写回
0x80485c4 add [ebp-0x58],0x00000001

0x80485c8 cmp [ebp-0x58],0x00000024
0x80485cc jna 0x804853c

0x80485d2

试着解

1
2
3
4
5
6
7
s = "t1me_y0u_enj0y_wa5t1ng_wa5_not_wa5ted"
for i in s:
if ord(i) + 3 < ord('Z'):
i = chr(3 + ord(i))
else:
i = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[(ord(i) + 3 - ord('Z')) % 26 - 1]
print(i,end='')

对了

RCTF{C4VNHH3DHNWS3HHFJ8C4WPHFJ8HWXCHFJ8CNM}

文章作者: Usher
文章链接: https://usher2008.github.io/2021/09/13/RCTF/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Usher