PwnCollege - RE - Internal State Mini

Internal State Mini (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
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
char desired_output[] = "\x1b[38;2;200;040;131mc\x1b[0m\x1b[38;2;001;019;165mI\x1b[0m\x1b[38;2;160;134;059mM\x1b[0m\x1b[38;2;195;046;079mG\x1b[0m\x00";

// 4 + 2 + 1 + 1 = 8 bytes header
struct cimg_header
{
char magic_number[4];
uint16_t version;
uint8_t width;
uint8_t height;
} __attribute__((packed));

// 1 byte ascii
typedef struct
{
uint8_t ascii;
} pixel_bw_t;
#define COLOR_PIXEL_FMT "\x1b[38;2;%03d;%03d;%03dm%c\x1b[0m"

// 3 rgb + 1 ascii
typedef struct
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t ascii;
} pixel_color_t;
typedef pixel_color_t pixel_t;

// text ansi escape sequence (24 bytes)
typedef struct
{
union
{
char data[24];
struct term_str_st
{
char color_set[7]; // \x1b[38;2;
char r[3]; // 255
char s1; // ;
char g[3]; // 255
char s2; // ;
char b[3]; // 255
char m; // m
char c; // X
char color_reset[4]; // \x1b[0m
} str;
};
} term_pixel_t;
struct cimg
{
struct cimg_header header;
unsigned num_pixels;
term_pixel_t *framebuffer;
};

#define CIMG_NUM_PIXELS(cimg) ((cimg)->header.width * (cimg)->header.height)
#define CIMG_DATA_SIZE(cimg) (CIMG_NUM_PIXELS(cimg) * sizeof(pixel_t))
#define CIMG_FRAMEBUFFER_PIXELS(cimg) ((cimg)->header.width * (cimg)->header.height)
#define CIMG_FRAMEBUFFER_SIZE(cimg) (CIMG_FRAMEBUFFER_PIXELS(cimg) * sizeof(term_pixel_t))

// ...

int main(int argc, char **argv, char **envp)
{

struct cimg cimg = { 0 };
cimg.framebuffer = NULL;
int won = 1;

if (argc > 1)
{
if (strcmp(argv[1]+strlen(argv[1])-5, ".cimg"))
{
printf("ERROR: Invalid file extension!");
exit(-1);
}
dup2(open(argv[1], O_RDONLY), 0);
}

read_exact(0, &cimg.header, sizeof(cimg.header), "ERROR: Failed to read header!", -1);

// magic_number
if (cimg.header.magic_number[0] != 'c' || cimg.header.magic_number[1] != 'I' || cimg.header.magic_number[2] != 'M' || cimg.header.magic_number[3] != 'G')
{
puts("ERROR: Invalid magic number!");
exit(-1);
}

// version
if (cimg.header.version != 2)
{
puts("ERROR: Unsupported version!");
exit(-1);
}

initialize_framebuffer(&cimg);

unsigned long data_size = cimg.header.width * cimg.header.height * sizeof(pixel_t);
pixel_t *data = malloc(data_size);
if (data == NULL)
{
puts("ERROR: Failed to allocate memory for the image data!");
exit(-1);
}
read_exact(0, data, data_size, "ERROR: Failed to read data!", -1);

for (int i = 0; i < cimg.header.width * cimg.header.height; i++)
{
// ascii
if (data[i].ascii < 0x20 || data[i].ascii > 0x7e)
{
fprintf(stderr, "ERROR: Invalid character 0x%x in the image data!\n", data[i].ascii);
exit(-1);
}
}

display(&cimg, data);

// char desired_output[] = "\x1b[38;2;200;040;131mc\x1b[0m\x1b[38;2;001;019;165mI\x1b[0m\x1b[38;2;160;134;059mM\x1b[0m\x1b[38;2;195;046;079mG\x1b[0m\x00";
if (cimg.num_pixels != sizeof(desired_output)/sizeof(term_pixel_t))
{
won = 0;
}
for (int i = 0; i < cimg.num_pixels && i < sizeof(desired_output)/sizeof(term_pixel_t); i++)
{
if (cimg.framebuffer[i].str.c != ((term_pixel_t*)&desired_output)[i].str.c)
{
won = 0;
}
if (
cimg.framebuffer[i].str.c != ' ' &&
cimg.framebuffer[i].str.c != '\n' &&
memcmp(cimg.framebuffer[i].data, ((term_pixel_t*)&desired_output)[i].data, sizeof(term_pixel_t))
)
{
won = 0;
}
}

if (won) win();
}
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
from pwn import *
from pwn import process

header = b"cIMG"
version = 2
width = 4
height = 1
total_pixels = width * height

file_header = struct.pack("<4sHBB", header,version, width, height)

p1 = struct.pack("<BBBB", 200, 40, 131, ord('c'))
p2 = struct.pack("<BBBB", 1, 19, 165, ord('I'))
p3 = struct.pack("<BBBB", 160, 134, 59, ord('M'))
p4 = struct.pack("<BBBB", 195, 46, 79, ord('G'))

pixel_data = p1 + p2 + p3 + p4

payload = file_header + pixel_data

file = open("payload.cimg", "wb")
file.write(payload)
file.close()

p = process(["/challenge/cimg", "payload.cimg"], stdin=process.PTY, stdout=process.PTY)
print(p.recvall())

pwn.college{**********************************************}

Internal State Mini (x86)

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
       ╎╎   0x00401387      4863db         movsxd rbx, ebx
╎╎ 0x0040138a 48c1e302 shl rbx, 2
╎╎ 0x0040138e 4889df mov rdi, rbx
╎╎ 0x00401391 e86afeffff call sym.imp.malloc ;[1]
╎╎ 0x00401396 488d3d1e0e.. lea rdi, str.ERROR:_Failed_to_allocate_memory_for_the_image_data_ ; 0x4021bb ; "ERROR: Failed to all
╎╎ 0x0040139d 4889c5 mov rbp, rax
╎╎ 0x004013a0 4885c0 test rax, rax
╎└─< 0x004013a3 74b1 je 0x401356
╎ 0x004013a5 89da mov edx, ebx
╎ 0x004013a7 4889c6 mov rsi, rax
╎ 0x004013aa 4183c8ff or r8d, 0xffffffff ; -1
╎ 0x004013ae 31ff xor edi, edi
╎ 0x004013b0 488d0d390e.. lea rcx, str.ERROR:_Failed_to_read_data_ ; 0x4021f0 ; "ERROR: Failed to read data!"
╎ 0x004013b7 e8bf020000 call sym.read_exact ;[2]
╎ 0x004013bc 0fb6442407 movzx eax, byte [rsp + 7]
╎ 0x004013c1 0fb6542406 movzx edx, byte [rsp + 6]
╎ 0x004013c6 0fafd0 imul edx, eax
╎ 0x004013c9 31c0 xor eax, eax
╎┌─> 0x004013cb 39c2 cmp edx, eax
┌───< 0x004013cd 7e30 jle 0x4013ff
│╎╎ 0x004013cf 0fb64c8503 movzx ecx, byte [rbp + rax*4 + 3]
│╎╎ 0x004013d4 48ffc0 inc rax
│╎╎ 0x004013d7 8d71e0 lea esi, [rcx - 0x20]
│╎╎ 0x004013da 4080fe5e cmp sil, 0x5e ; '^' ; 94
│╎└─< 0x004013de 76eb jbe 0x4013cb
│╎ 0x004013e0 488b3dd92c.. mov rdi, qword [obj.stderr] ; obj.stderr__GLIBC_2.2.5
│╎ ; [0x4040c0:8]=0
│╎ 0x004013e7 488d151e0e.. lea rdx, str.ERROR:_Invalid_character_0x_x_in_the_image_data__n ; str.ERROR:_Invalid_character_0x_x_
│╎ ; 0x40220c ; "ERROR: Invalid character 0x%x in the image data!\n"
│╎ 0x004013ee be01000000 mov esi, 1
│╎ 0x004013f3 31c0 xor eax, eax
│╎ 0x004013f5 e856feffff call sym.imp.__fprintf_chk ;[3]
│└──< 0x004013fa e95cffffff jmp 0x40135b
└───> 0x004013ff 4889ee mov rsi, rbp
0x00401402 4c89e7 mov rdi, r12
0x00401405 4c8d25142c.. lea r12, obj.desired_output ; 0x404020 ; color ; go to check desired_output
0x0040140c 31db xor ebx, ebx
0x0040140e e8b8020000 call sym.display ;[4]
0x00401413 448b6c2408 mov r13d, dword [rsp + 8]
0x00401418 4c8b742410 mov r14, qword [rsp + 0x10]
0x0040141d 4183fd04 cmp r13d, 4 ; 4 ; pixel size
0x00401421 0f94c3 sete bl
0x00401424 31ed xor ebp, ebp
0x00401426 4531ff xor r15d, r15d
┌─> 0x00401429 83fd04 cmp ebp, 4 ; 4
┌──< 0x0040142c 743e je 0x40146c
│╎ 0x0040142e 4139ed cmp r13d, ebp
┌───< 0x00401431 7639 jbe 0x40146c
││╎ 0x00401433 486bfd18 imul rdi, rbp, 0x18
││╎ 0x00401437 418a443e13 mov al, byte [r14 + rdi + 0x13]
││╎ 0x0040143c 413a442413 cmp al, byte [r12 + 0x13]
││╎ 0x00401441 410f45df cmovne ebx, r15d
││╎ 0x00401445 3c20 cmp al, 0x20 ; 32
┌────< 0x00401447 741a je 0x401463
│││╎ 0x00401449 3c0a cmp al, 0xa ; 10
┌─────< 0x0040144b 7416 je 0x401463
││││╎ 0x0040144d 4c01f7 add rdi, r14
││││╎ 0x00401450 ba18000000 mov edx, 0x18 ; 24
││││╎ 0x00401455 4c89e6 mov rsi, r12
││││╎ 0x00401458 e883fdffff call sym.imp.memcmp ;[5]
││││╎ 0x0040145d 85c0 test eax, eax
││││╎ 0x0040145f 410f45df cmovne ebx, r15d
└└────> 0x00401463 48ffc5 inc rbp
││╎ 0x00401466 4983c418 add r12, 0x18 ; 24
││└─< 0x0040146a ebbd jmp 0x401429
└└──> 0x0040146c 85db test ebx, ebx
┌─< 0x0040146e 7407 je 0x401477
│ 0x00401470 31c0 xor eax, eax
│ 0x00401472 e80f010000 call sym.win ;[6]
└─> 0x00401477 488b442418 mov rax, qword [rsp + 0x18]
0x0040147c 6448330425.. xor rax, qword fs:[0x28]
┌─< 0x00401485 7405 je 0x40148c
│ 0x00401487 e804fdffff call sym.imp.__stack_chk_fail ;[7]
└─> 0x0040148c 4883c428 add rsp, 0x28

> px 96 @ 0x404020
- offset - 2021 2223 2425 2627 2829 2A2B 2C2D 2E2F 0123456789ABCDEF
0x00404020 1b5b 3338 3b32 3b31 3534 3b31 3732 3b30 .[38;2;154;172;0
0x00404030 3130 6d63 1b5b 306d 1b5b 3338 3b32 3b30 10mc.[0m.[38;2;0
0x00404040 3533 3b30 3935 3b32 3235 6d49 1b5b 306d 53;095;225mI.[0m
0x00404050 1b5b 3338 3b32 3b31 3332 3b30 3934 3b30 .[38;2;132;094;0
0x00404060 3637 6d4d 1b5b 306d 1b5b 3338 3b32 3b32 67mM.[0m.[38;2;2
0x00404070 3035 3b30 3336 3b30 3836 6d47 1b5b 306d 05;036;086mG.[0m
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
from pwn import *
from pwn import process

header = b"cIMG"
version = 2
width = 4
height = 1
total_pixels = width * height

file_header = struct.pack("<4sHBB", header,version, width, height)

p1 = struct.pack("<BBBB", 154, 172, 10, ord('c'))
p2 = struct.pack("<BBBB", 53, 95, 225, ord('I'))
p3 = struct.pack("<BBBB", 132, 94, 67, ord('M'))
p4 = struct.pack("<BBBB", 205, 36, 86, ord('G'))

pixel_data = p1 + p2 + p3 + p4

payload = file_header + pixel_data

file = open("payload.cimg", "wb")
file.write(payload)
file.close()

p = process(["/challenge/cimg", "payload.cimg"], stdin=process.PTY, stdout=process.PTY)
print(p.recvall())

pwn.college{***********************************************}