NewStar2024部分Reverse与Crypto

Re

week2

ptrace

1
fork` 函数会返回两次:一次在父进程中返回子进程的 `pid`,一次在子进程中返回 `0

如果 v11 > 0,表示这是父进程,如果 v11 == 0,表示这是子进程,如果 v11 < 0,表示 fork 失败

可以不看father,直接加参数调试

个人觉得题目出错了

1
2
3
4
5
6
7
8
9
a=[0xCC, 0x8D, 0x2C, 0xEC, 0x6F, 0x88, 0xED, 0xEB, 0x2F, 0xED,
0xAE, 0xEB, 0x4E, 0xAC, 0x2C, 0x8D, 0x8D, 0x2F, 0xEB, 0x6D,
0xCD, 0xED, 0xEE, 0xEB, 0x0E, 0x8E, 0x4E, 0x2C, 0x6C, 0xAC,
0xE7, 0xAF]
for i in range(len(a)):
a[i]=((a[i]>>5)|(a[i]<<3)%256)
print(chr(a[i]),end="")

#flag{Do_you_really_know_ptrace?}

week3

simpleAndroid

native层实现逻辑,动态注册,看JNI_Onload函数

看CheckActivity类,发现CheckData

加载UseLess,并重新设置 CHAR_DATA ,后续调用base64

后续首尾调换再高低位互换

1
2
3
4
5
6
7
8
9
10
11
12
a=[0xB2, 0x74, 0x45, 0x16, 0x47, 0x34, 0x95, 0x36, 0x17, 0xF4,
0x43, 0x95, 0x03, 0xD6, 0x33, 0x95, 0xC6, 0xD6, 0x33, 0x36,
0xA7, 0x35, 0xE6, 0x36, 0x96, 0x57, 0x43, 0x16, 0x96, 0x97,
0xE6, 0x16]
s=''
for i in range(len(a)):
a[i]=((a[i]<<4)|(a[i]>>4))%256
for i in range(len(a)//2):
a[i],a[len(a)-i-1]=a[len(a)-i-1],a[i]
for i in range(len(a)):
s+=chr(a[i])
print(s)

SMC_math

smc处理得好就是标准z3,可以先全undefine在force

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
from z3 import *
import libnum
v2=BitVec('v2',32)
v3=BitVec('v3',32)
v4=BitVec('v4',32)
v5=BitVec('v5',32)
v6=BitVec('v6',32)
v7=BitVec('v7',32)
v8=BitVec('v8',32)

sovler=Solver()
a=[]
sovler.add(5 * (v3 + v2) + 4 * v4 + 6 * v5 + v6 + 9 * v8 + 2 * v7==0xD5CC7D4FF)
sovler.add(4 * v8 + 3 * v5 + 6 * v4 + 10 * v3 + 9 * v2 + 9 * v7 + 3 * v6==0x102335844B)
sovler.add(9 * v6 + 4 * (v5 + v4) + 5 * v3 + 4 * v2 + 3 * v8 + 10 * v7==0xD55AEABB9)
sovler.add(9 * v3 + 5 * v2 + 9 * v8 + 2 * (v4 + 2 * v5 + 5 * v6 + v7)==0xF89F6B7FA)
sovler.add(5 * v6 + 9 * v5 + 7 * v2 + 2 * v3 + v4 + 3 * v8 + 9 * v7==0xD5230B80B)
sovler.add(8 * v8 + 6 * v5 + 10 * v4 + 5 * v3 + 6 * v2 + 3 * v7 + 9 * v6==0x11E28ED873)
sovler.add(v2 + 4 * (v4 + v3 + 2 * v5) + 9 * v6 + v7 + 3 * v8 == 0xB353C03E1)
if sovler.check()==sat:
model=sovler.model()
print(libnum.n2s(model[v2].as_long())[::-1].decode(), end='')
print(libnum.n2s(model[v3].as_long())[::-1].decode(), end='')
print(libnum.n2s(model[v4].as_long())[::-1].decode(), end='')
print(libnum.n2s(model[v5].as_long())[::-1].decode(), end='')
print(libnum.n2s(model[v6].as_long())[::-1].decode(), end='')
print(libnum.n2s(model[v7].as_long())[::-1].decode(), end='')
print(libnum.n2s(model[v8].as_long())[::-1].decode(), end='')

wtf

交叉引用input都下好断点,然后调试运行看程序逻辑,发现先-0xe9再^i

1
2
3
4
5
6
7
8
a=[0x4F, 0x54, 0x48, 0x53, 0x60, 0x45, 0x37, 0x1A, 0x28, 0x41,
0x26, 0x16, 0x3B, 0x45, 0x14, 0x47, 0x0E, 0x0C, 0x70, 0x3B,
0x3C, 0x3D, 0x70]
s=''
for i in range(len(a)):
a[i]=a[i]^i
s+=chr((a[i]-0xe9)%256)
print(s)

011vm

用d810去混淆但不完全

进入3b30,一个打印一个tea,找到tea的所有参数,前后一一对应

上面是密钥,下面是密文

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

int main() {
uint32_t v[2] = {1, 2};
uint32_t v0 = v[0], v1 = v[1], sum=0, i; /* set up */
uint32_t delta = 0x9E3779B9;
uint32_t v2[2] = {0x3D121D26, 0x5E6189F9}, v3[2] = {0xC1FB278E, 0x3B494648}, v5[10] = {0x38B97E28,0xB7E510C1,0xB4B29FAE,0x5593BBD7,0x3C2E9B9E,0x1671C637,0x8F3A8CB5,0x5116E515};
unsigned int k[4] = {0x11121314,0x22232425,0x33343536,0x41424344}, l = 0, r = 0;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for(int m=0;m<8;m+=2){
sum = delta*(32);
for (i = 0; i < 32; i++) {
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;
}
}


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

return 0;
}

flowering_shrubs

静态去花指令发现是函数嵌套函数,吓了一跳,果断选择动态,发现还是一样

密文一次循环变化四位,逻辑在上面

调试出对应关系,这样就不用管随机数了

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
'''
0->u
1->a
8->r
3->e
2->f
6->i
4->r
5->s
7->t
9->.
'''

s='uafersitr.'

a=[0x54, 0xF4, 0x20, 0x47, 0xFC, 0xC4, 0x93, 0xE6, 0x39, 0xE0,
0x6E, 0x00, 0xA5, 0x6E, 0xAA, 0x9F, 0x7A, 0xA1, 0x66, 0x39,
0x76, 0xB7, 0x67, 0x57, 0x3D, 0x95, 0x61, 0x22, 0x55, 0xC9,
0x3B, 0x4E, 0x4F, 0xE8, 0x66, 0x08, 0x3D, 0x50, 0x43, 0x3E]
for i in range(0,len(s)*4,4):
a[i]=a[i]^a[i+3]
a[i+3]^=a[i+2]
a[i+2]=a[i+2]+ord(s[i//4])
a[i+2]^=a[i+1]
a[i+1]=a[i+1]-ord(s[i//4])
a[i+1]^=a[i]
a[i]^=ord(s[i//4])
# print(a)
print(chr((a[i])%256),end="")
print(chr((a[i+1])%256), end="")
print(chr((a[i+2])%256), end="")
print(chr((a[i+3])%256), end="")
#flag{y0u_C4n_3a51ly_Rem0v3_CoNfu510n-!!}

SecretsofKawayi

先rc4再base64

so文件先脱壳,发现是魔改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
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 <stdio.h>
#include <stdint.h>
#define DELTA 0x21524111
#define MX (((z>>5^y<<3) + (y>>3^z<<2)) ^ ((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 = (-rounds)*DELTA;
z = v[n - 1];
do {
e = (sum >> 2) & 3;
for (p = n-1; p >0; p--) {
y = v[p + 1];
z = v[p] -= MX;
}
y = v[0];
z = v[n - 1] -= MX;
sum += DELTA;
} 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[12] = {0x8C12D3DF, 0x5F4C4137, 0x1A9D3D02, 0x2D1294B7, 0xFB622B37, 0xD18D84E3, 0x064C4592, 0x16985CAB, 0xFDB06D69,0xFB30B1E3,0x925C2FD3,0x2E1BB40C};
uint32_t const k[4] = {0x776F656D, 0x6F656D7E, 0x65747E77, 0x7E7E7E61};
int n = 12;//注意这里与数组长度相等
btea(v, -n, k);
for (int i = 0; i < 12; i ++) {
printf("%x,", v[i]&0xff);
printf("%x,", v[i] >> 8 & 0xff);
printf("%x,", v[i] >> 16 & 0xff);
printf("%x,", v[i] >> 24 & 0xff);
}
printf("\n");


return 0;
}
import base64
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([113, 71, 105, 111, 84, 56, 107, 115, 98, 118, 72, 105, 102, 105, 111, 77, 89, 100, 113, 47, 104, 66, 115, 112, 82, 76, 52, 67, 82, 122, 70, 86, 79, 47, 89, 98, 103, 78, 89, 100, 67, 103, 61, 61, 10, 0, 0, 0])
key = b'rc4k4y'


data=base64.b64decode(data)
decrypted = rc4(data, key)
print(decrypted)

Crypto

week2

茶里茶气

>>和tea的结合

因为%p,所以每一轮算完都小于p且是正数,那么只要小于0的时候+p即可,得到高低位后移位再相加即可

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

# flag = "flag{*****}"
# assert len( flag ) == 25
#
# a = ""
# for i in flag:
# a += hex(ord(i))[2:]
# l = int(a,16).bit_length()
# print("l =" , l )

# v0 = int(a,16)>>(l//2)
# v1 = int(a,16)-(v0<<(l//2))
# p = getPrime(l//2+10)


derta = 462861781278454071588539315363
v2 = derta*32
v3 = 489552116384728571199414424951
v4 = 469728069391226765421086670817
v5 = 564098252372959621721124077407
v6 = 335640247620454039831329381071
# assert v1 < p and v0 < p and derta < p and v3 < p and v4 < p and v5 < p and v6 < p

v0 = 190997821330413928409069858571234
v1 = 137340509740671759939138452113480
p = 446302455051275584229157195942211
for i in range(32):
v2 -= derta
while v2 < 0:
v2 += p
v0 -= (v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 )
while v0<0:
v0+=p
v1 -= (v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 )
while v1<0:
v1+=p


print( "v0 =" , v0 )
print( "v1 =" , v1 )

v0_2_v1 = 1014351839000028912764735400942<<99
v1 = 348231531876293114407512127357
print(hex(v0_2_v1+v1))

NewStar2024部分Reverse与Crypto
https://j1ya-22.github.io/2024/10/23/NewStar2024部分Reverse与Crypto/
作者
j1ya
发布于
2024年10月23日
许可协议