0%

2024强网拟态初赛 Re部分WP

Reverse

serv1ce

有点混淆,jeb5直接反编译解出字符串,然后就可以找他的startService

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
package com.nobody.Serv1ce;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class MyService extends Service {
private String input;
private String key;
private byte[] keyarray;
int num;

static {
System.loadLibrary("Serv1ce");
}

public MyService() {
this.key = "1liIl11lIllIIl11llII";
this.keyarray = new byte[0x40];
this.num = 9;
}

private native boolean check(String arg1, byte[] arg2, int arg3) {
}

@Override // android.app.Service
public IBinder onBind(Intent intent0) {
throw new UnsupportedOperationException("Not yet implemented");
}

@Override // android.app.Service
public void onCreate() {
++this.num;
super.onCreate();
}

@Override // android.app.Service
public void onDestroy() {
if(this.check(this.input, this.keyarray, this.num)) {
Toast.makeText(this.getApplicationContext(), "You Are Right", 1).show();
}
else {
Toast.makeText(this.getApplicationContext(), "Wrong", 1).show();
}

super.onDestroy();
}

@Override // android.app.Service
public int onStartCommand(Intent intent0, int v, int v1) {
++this.num;
for(int v2 = 0; v2 < 0x40; ++v2) {
this.keyarray[v2] = (byte)((this.key.charAt(v2 % this.key.length()) - 0x77 ^ 23) & 0xFF);
}

if(intent0 != null) {
this.input = intent0.getStringExtra("input");
Toast.makeText(this.getApplicationContext(), "Input Success", 1).show();
}

super.onStartCommand(intent0, v, v1);
return v;
}
}

image.png
exp

1
2
3
4
5
6
7
8
9
10
11
12
res = [0xB9, 0x32, 0xC2, 0xD4, 0x69, 0xD5, 0xCA, 0xFB, 0xF8, 0xFB, 0x80, 0x7C, 0xD4, 0xE5, 0x93, 0xD5, 0x1C, 0x8B, 0xF8, 0xDF, 0xDA, 0xA1, 0x11, 0xF8, 0xA1, 0x93, 0x93, 0xC2, 0x7C, 0x8B, 0x1C, 0x66, 0x01, 0x3D, 0xA3, 0x67]

key = "1liIl11lIllIIl11llII"
keyarray = [0 for i in range(0x40)]
for i in range(0x40):
keyarray[i] =((ord(key[i%len(key)])-0x77)^23)&0xff
print(keyarray)
for i in range(36):
# print(i)
for num in string.printable:
if ((ord(num)^keyarray[i])*11)&0xff == res[i]:
print(num,end='')

A_game

NJU-TJL/PacManX: 基于C++控制台(Windows平台)的一个吃豆人小游戏 (github.com)

image.png

bindiff结果

下面几个就是出题人改的跟flag有关的函数了

动调把ps脚本扣出来,里面好几层iex,运行输出一下 iex后面的部分

最内层:

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

function enenenenene {
param(
$plaintextBytes,
$keyBytes
)
# Initialize S and KSA
$S = 0..255
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $S[$i] + $keyBytes[$i % $keyBytes.Length]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
}

# PRGA and encryption
$i = 0
$j = 0
$ciphertextBytes = @()
for ($k = 0; $k -lt $plaintextBytes.Length; $k++) {
$i = ($i + 1) % 256
$j = ($j + $S[$i]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
$t = ($S[$i] + $S[$j]) % 256
$ciphertextBytes += ($plaintextBytes[$k] -bxor $S[$t])
}

# Return ciphertext as a string
return $ciphertextBytes
}
function enenenenene1 {
param(
$inputbyte
)
$key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = @();
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$encryptedText = enenenenene -plaintextBytes $inputbyte -keyBytes $key;
$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
}
return $encryptedText + $key;
}
function enenenenene2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] + $key[$k % $key.Length]
}
return $inputbyte;
}
function enenenenene3 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] * $key[$k % $key.Length]
}
return $inputbyte;
}
$registryPath = 'HKCU:\Software\PacManX'
$valueName = 'MYFLAG'
$value = Get-ItemPropertyValue $registryPath $valueName
$plaintext = @($value) | ForEach-Object {
$input = $_
$plaintext = @()
for ($i = 0; $i -lt $input.Length; $i++) {
$plaintext += [int][char]$input[$i]
}
$plaintext
}
if ($plaintext.Length -ne 36) {
Set-Content -Path "log.txt" -Value "ERROR"
exit
}
$encrypted1Text = enENenenene2 -inputbyte (enenenENene2 -inputbyte (enenenenene3 -inputbyte (Enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene1 -input $plaintext))))))
$result = @(38304, 8928, 43673, 25957 , 67260, 47152, 16656, 62832 , 19480 , 66690, 40432, 15072 , 63427 , 28558 , 54606, 47712 , 18240 , 68187 , 18256, 63954 , 48384, 14784, 60690 , 21724 , 53238 , 64176 , 9888 , 54859 , 23050 , 58368 , 46032 , 15648 , 64260 , 17899 , 52782 , 51968 , 12336 , 69377 , 27844 , 43206 , 63616)
for ($k = 0; $k -lt $result.Length; $k++) {
if ($encrypted1Text[$k] -ne $result[$k]) {
Set-Content -Path "log.txt" -Value "ERROR"
exit

}
Set-Content -Path "log.txt" -Value "RIGHT"

enenenenene 就是个rc4,加密解密一样,powershell写个解密exp

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
# execute: powershell -executionpolicy bypass -file .\exp.ps1
function enenenenene { # rc4
param(
$plaintextBytes,
$keyBytes
)
# Initialize S and KSA
$S = 0..255
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $S[$i] + $keyBytes[$i % $keyBytes.Length]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
}

# PRGA and encryption
$i = 0
$j = 0
$ciphertextBytes = @()
for ($k = 0; $k -lt $plaintextBytes.Length; $k++) {
$i = ($i + 1) % 256
$j = ($j + $S[$i]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
$t = ($S[$i] + $S[$j]) % 256
$ciphertextBytes += ($plaintextBytes[$k] -bxor $S[$t])
}

# Return ciphertext as a string
return $ciphertextBytes
}
function enc1 {
param(
$inputbyte
)
$key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = @();
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$encryptedText = enenenenene -plaintextBytes $inputbyte -keyBytes $key;
$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
}
return $encryptedText + $key;
}
function dec1 {
param(
$inputbyte
)
$initial_key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = $inputbyte[0..($inputbyte.Length-$initial_key.Length-1)]
$key = $inputbyte[($inputbyte.Length-$initial_key.Length)..($inputbyte.Length-1)]
# Write-Output $encryptedText
# Write-Output $key
# Write-Output $encryptedText

$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
$plain = enenenenene -plaintextBytes $encryptedText -keyBytes $key;
return $plain;
}
function enc2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] + $key[$k % $key.Length]
}
return $inputbyte;
}

function dec2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] - $key[$k % $key.Length]
}
return $inputbyte;
}

function enc3 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] * $key[$k % $key.Length]
}
return $inputbyte;
}

function dec3 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] / $key[$k % $key.Length]
}
return $inputbyte;
}

# $registryPath = 'HKCU:\Software\PacManX'
# $valueName = 'MYFLAG'
# $value = Get-ItemPropertyValue $registryPath $valueName
# $plaintext = @($value) | ForEach-Object {
# $input = $_
# $plaintext = @()
# for ($i = 0; $i -lt $input.Length; $i++) {
# $plaintext += [int][char]$input[$i]
# }
# $plaintext
# }
# if ($plaintext.Length -ne 36) {
# Set-Content -Path "log.txt" -Value "ERROR"
# exit
# }
# $encrypted1Text = enENenenene2 -inputbyte (enenenENene2 -inputbyte (enenenenene3 -inputbyte (Enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene1 -input $plaintext))))))

Write-Host (dec1 -inputbyte (enc1 -inputbyte @(1, 2, 3, 4, 5)))
Write-Host (dec2 -inputbyte (enc2 -inputbyte @(1, 2, 3, 4, 5)))
Write-Host (dec3 -inputbyte (enc3 -inputbyte @(1, 2, 3, 4, 5)))

$result = @(38304, 8928, 43673, 25957 , 67260, 47152, 16656, 62832 , 19480 , 66690, 40432, 15072 , 63427 , 28558 , 54606, 47712 , 18240 , 68187 , 18256, 63954 , 48384, 14784, 60690 , 21724 , 53238 , 64176 , 9888 , 54859 , 23050 , 58368 , 46032 , 15648 , 64260 , 17899 , 52782 , 51968 , 12336 , 69377 , 27844 , 43206 , 63616)

$flag = dec1 -inputbyte (dec2 -inputbyte (dec2 -inputbyte (dec2 -inputbyte (dec3 -inputbyte (dec2 -inputbyte (dec2 -inputbyte $result))))))

$flag = [System.Text.Encoding]::ASCII.GetString($flag)

Write-Host $flag

flag: 73412036-7d8c-437b-9026-0c2ca1b7f79d

babyre

流程大概如下,可以根据S盒+调试确定是AES,轮数也是10

image.png

image.png

phrase函数把8bit输入和4bit索引合在一起变成12bit

image.png

check函数判断给定的12bit是否符合任一条件,即图中这一堆&v1&(v2==0),由于12bit里面有4bit索引,所以能过这个check的输入是固定的

爆破得到所有能过check的12bit输入

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
#include"defs.h" 
#include<stdio.h>
__int64 __fastcall sub_4020F7(int *a1)
{
int v1; // r8d
int v2; // ecx
int v3; // ecx
int v5; // [rsp+8h] [rbp-38h]
int v6; // [rsp+Ch] [rbp-34h]
int v7; // [rsp+10h] [rbp-30h]
int v8; // [rsp+14h] [rbp-2Ch]
int v9; // [rsp+18h] [rbp-28h]
int v10; // [rsp+1Ch] [rbp-24h]
int v11; // [rsp+20h] [rbp-20h]
int v12; // [rsp+24h] [rbp-1Ch]
int v13; // [rsp+28h] [rbp-18h]
int v14; // [rsp+2Ch] [rbp-14h]
__int64 v15; // [rsp+30h] [rbp-10h]
int i; // [rsp+38h] [rbp-8h]
unsigned int v17; // [rsp+3Ch] [rbp-4h]

v17 = 1;
for ( i = 0; i <= 0; ++i )
{
HIDWORD(v15) = a1[12 * i];
LODWORD(v15) = a1[12 * i + 1];
v14 = a1[12 * i + 2];
v13 = a1[12 * i + 3];
v12 = a1[12 * i + 4];
v11 = a1[12 * i + 5];
v10 = a1[12 * i + 6];
v9 = a1[12 * i + 7];
v8 = a1[12 * i + 8];
v7 = a1[12 * i + 9];
v6 = a1[12 * i + 10];
v5 = a1[12 * i + 11];
v1 = (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v9 & (v11 == 0) & (v12 == 0) & (unsigned __int8)v13 & ((v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v10 == 0) & (v6 == 0) | (unsigned __int8)v7 & (unsigned __int8)v9 & (unsigned __int8)v11 & (v13 == 0) & (v14 == 0) & BYTE4(v15) & ((_DWORD)v15 == 0) & (v12 == 0) & (v10 == 0) & (v8 == 0) & (v6 == 0) | (unsigned __int8)v6 & (v8 == 0) & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & (unsigned __int8)v12 & (unsigned __int8)(v14 & v15 & BYTE4(v15)) & (v13 == 0) & (v7 == 0);
v2 = (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v8 & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)(v15 & BYTE4(v15)) & (v13 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (unsigned __int8)v8 & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v12 & (unsigned __int8)v13 & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v14 == 0) & (v11 == 0) & (v5 == 0) | (unsigned __int8)v5 & (v7 == 0) & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & (unsigned __int8)v13 & (unsigned __int8)v14 & BYTE4(v15) & ((_DWORD)v15 == 0) & (v11 == 0) & (v9 == 0) & (v6 == 0) | (unsigned __int8)v5 & (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v13 & (unsigned __int8)v14 & (v15 == 0) & (v12 == 0) & (v9 == 0) & (v6 == 0) | (v1 | (unsigned __int8)v6 & (unsigned __int8)v7 & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (unsigned __int8)v13 & (unsigned __int8)v14 & BYTE4(v15) & ((_DWORD)v15 == 0) & (v11 == 0) & (v8 == 0)) & (v5 == 0);
v3 = (unsigned __int8)v5 & (unsigned __int8)v6 & (v8 == 0) & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (v13 == 0) & (v14 == 0) & (unsigned __int8)(v15 & BYTE4(v15)) & (v11 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (v8 == 0) & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (unsigned __int8)v13 & ((v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v11 == 0) & (v5 == 0) | (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v7 & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v13 == 0) & (v8 == 0) | (unsigned __int8)v5 & (unsigned __int8)v7 & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & ((v12 | v13 | v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v8 == 0) & (v6 == 0) | (unsigned __int8)v5 & (v7 == 0) & (v8 == 0) & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & BYTE4(v15) & ((_DWORD)v15 == 0) & (v13 == 0) & (v6 == 0) | v2;
if ( !((unsigned __int8)v6 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v13 == 0) & (v11 == 0) & (v9 == 0) & (v7 == 0) & (v5 == 0) | (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v7 & (unsigned __int8)v8 & (v10 == 0) & (v11 == 0) & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v13 == 0) & (v9 == 0) | v3 | (unsigned __int8)v6 & (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & ((v13 | v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v11 == 0) & (v9 == 0) & (v5 == 0)) )
v17 = 0;
}
return v17;
}
int main(){
int res[13];
int num;
for(int i=0;i<=(1<<12);i++){
res[0] = i&1;
res[1] = (i>>1)&1;
res[2] = (i>>2)&1;
res[3] = (i>>3)&1;
res[4] = (i>>4)&1;
res[5] = (i>>5)&1;
res[6] = (i>>6)&1;
res[7] = (i>>7)&1;
res[8] = (i>>8)&1;
res[9] = (i>>9)&1;
res[10] = (i>>10)&1;
res[11] = (i>>11)&1;
if(sub_4020F7(res)){
// printf("%d\n",i);
// for(int j=0;j<=11;j++){
// printf("%d ",res[j]);
// }
num = res[8];
num = (num<<1) + res[9];
num = (num<<1) + res[10];
num = (num<<1) + res[11];
printf("a[%d]=",num);
num = res[0];
num = (num<<1) + res[1];
num = (num<<1) + res[2];
num = (num<<1) + res[3];
num = (num<<1) + res[4];
num = (num<<1) + res[5];
num = (num<<1) + res[6];
num = (num<<1) + res[7];
printf("0x%x\n",num);
}
}
}
// data = [18,143,236,194,133,4,178,76,91,186,74,207,17,54,10,72]

AES key从程序里dump一份(0x405420):

1
3577402ECCA44A3F9AB72182F9B01F35

AES ECB解回去即可

image.png

加上uuid的横杠:

1
4d87ef03-77bb-491a-80f5-4620245807c4