Skip to content

Commit e34fdc1

Browse files
committed
Add decompiled kernel module line ctf pprofile
1 parent 3c61515 commit e34fdc1

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed

ctf/line-2021-pprofile/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Commands:
4747
- FREE -> Free a `string` from storages
4848
- READ -> The module with the READ operation will put inside the `request.garbage` address 8 bytes of 0, the pid value and the len value
4949

50+
[Kernel module decompiled](./pprofile-reversed.c)
51+
5052
## Exploitation
5153

5254
I tried at first some heap exploitation stuff but it didn't work.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
struct string {
2+
char *str;
3+
struct len_pid *info;
4+
}
5+
6+
struct len_pid {
7+
int64_t pad; // set always to 0
8+
int32_t pid; // the pid of the process that add the following structure
9+
int32_t len; // the length of str
10+
}
11+
12+
struct string *storages[16]; // global
13+
__int64 __fastcall pprofile_ioctl(__int64 a1, __int64 a2)
14+
{
15+
__int64 v2; // rdx
16+
__int64 result; // rax
17+
struct string **storages__; // rbx
18+
struct string *found_string_ptr_; // rbp
19+
__int64 v6; // rbx
20+
struct pid_len *found_info; // rax
21+
unsigned int found_pid; // ebp
22+
unsigned int found_size_str; // er12
23+
int len_copied; // eax
24+
int len_copied_; // ebx
25+
__int64 index_storage__; // rax
26+
__int64 index_storage___; // r12
27+
struct string **current_string__; // rbp
28+
size_t len_str; // rbp
29+
unsigned int len_str_plus_1; // er13
30+
_DWORD *str_ptr; // r15
31+
string *string_ptr; // r14
32+
struct pid_len *leak_ptr_current_task; // rcx
33+
unsigned __int64 current_task_; // rdi
34+
int len_copied__; // eax
35+
__int64 index_storage____; // rbp
36+
struct string *current_string; // r12
37+
__int64 current_string_ptr_str; // r13
38+
unsigned int index_zeroize_; // eax
39+
__int64 index_zeroize; // rdx
40+
struct pid_len *leak_ptr_current_task_; // [rsp+0h] [rbp-60h]
41+
__int64 local_buffer; // [rsp+8h] [rbp-58h] BYREF
42+
__int64 v29; // [rsp+10h] [rbp-50h]
43+
char str_copied[8]; // [rsp+1Fh] [rbp-41h] BYREF
44+
char v31; // [rsp+27h] [rbp-39h]
45+
unsigned __int64 v32; // [rsp+28h] [rbp-38h]
46+
47+
_fentry__(a1, a2);
48+
*(_QWORD *)str_copied = 0LL;
49+
v31 = 0;
50+
v32 = __readgsqword(0x28u);
51+
local_buffer = 0LL;
52+
v29 = 0LL;
53+
LODWORD(result) = copy_from_user(&local_buffer, v2, 16LL);
54+
if ( (_DWORD)result )
55+
return (int)result;
56+
if ( (_DWORD)a2 == 32 )
57+
{
58+
len_copied = strncpy_from_user(str_copied, local_buffer, 8LL);
59+
len_copied_ = len_copied;
60+
if ( len_copied && len_copied != 9 )
61+
{
62+
if ( len_copied >= 0 )
63+
{
64+
index_storage__ = 0LL;
65+
while ( 1 )
66+
{
67+
index_storage___ = (int)index_storage__;
68+
if ( !storages[index_storage__] )
69+
break;
70+
if ( ++index_storage__ == 16 )
71+
return -11LL;
72+
}
73+
current_string__ = storages;
74+
while ( !*current_string__ || strcmp((const char *)(*current_string__)->str, str_copied) )
75+
{
76+
if ( &storages[16] == ++current_string__ )
77+
{
78+
len_str = strlen(str_copied);
79+
if ( len_str - 1 > 7 )
80+
return -11LL;
81+
len_str_plus_1 = len_str + 1;
82+
str_ptr = (_DWORD *)_kmalloc(len_str + 1, 6291648LL);
83+
string_ptr = (string *)kmem_cache_alloc_trace(kmalloc_caches[4], 6291648LL, 16LL);
84+
leak_ptr_current_task = (struct pid_len *)kmem_cache_alloc_trace(kmalloc_caches[4], 6291648LL, 16LL);
85+
if ( string_ptr == 0LL || str_ptr == 0LL || !leak_ptr_current_task )
86+
return -12LL; //
87+
// Zeroize the str_ptr (kmalloc) in 4 different way xD, at least
88+
// from my understanding lol eheh
89+
// ... they don't know about kzalloc or memset X'D
90+
if ( len_str_plus_1 >= 8 )
91+
{
92+
*(_QWORD *)((char *)str_ptr + len_str_plus_1 - 8) = 0LL;
93+
if ( (unsigned int)len_str >= 8 )
94+
{
95+
index_zeroize_ = 0;
96+
do
97+
{
98+
index_zeroize = index_zeroize_;
99+
index_zeroize_ += 8;
100+
*(_QWORD *)((char *)str_ptr + index_zeroize) = 0LL;
101+
}
102+
while ( index_zeroize_ < (len_str & 0xFFFFFFF8) );
103+
}
104+
}
105+
else if ( (len_str_plus_1 & 4) != 0 )
106+
{
107+
*str_ptr = 0;
108+
*(_DWORD *)((char *)str_ptr + len_str_plus_1 - 4) = 0;
109+
}
110+
else if ( (_DWORD)len_str != -1 )
111+
{
112+
*(_BYTE *)str_ptr = 0;
113+
if ( (len_str_plus_1 & 2) != 0 )
114+
*(_WORD *)((char *)str_ptr + len_str_plus_1 - 2) = 0;
115+
}
116+
leak_ptr_current_task->pad = 0LL;
117+
*(_QWORD *)&leak_ptr_current_task->pid = 0LL;
118+
string_ptr->str = 0LL;
119+
string_ptr->info = 0LL;
120+
leak_ptr_current_task_ = leak_ptr_current_task;
121+
memcpy(str_ptr, str_copied, len_str);
122+
string_ptr->str = (__int64)str_ptr;
123+
current_task_ = __readgsqword((unsigned int)&current_task);
124+
string_ptr->info = leak_ptr_current_task_;
125+
leak_ptr_current_task_->pid = _task_pid_nr_ns(current_task_, 1LL, 0LL);
126+
*((_DWORD *)string_ptr->info + 3) = len_copied_;
127+
storages[index_storage___] = string_ptr;
128+
return len_copied_;
129+
}
130+
}
131+
return -11LL;
132+
}
133+
return len_copied_;
134+
}
135+
return -34LL;
136+
}
137+
if ( (_DWORD)a2 == 64 )
138+
{
139+
len_copied__ = strncpy_from_user(str_copied, local_buffer, 8LL);
140+
len_copied_ = len_copied__;
141+
if ( len_copied__ && len_copied__ != 9 )
142+
{
143+
if ( len_copied__ >= 0 )
144+
{
145+
index_storage____ = 0LL;
146+
while ( 1 )
147+
{
148+
current_string = storages[index_storage____];
149+
if ( current_string )
150+
{
151+
current_string_ptr_str = current_string->str;
152+
if ( !strcmp((const char *)current_string->str, str_copied) )
153+
break;
154+
}
155+
if ( ++index_storage____ == 16 )
156+
return -11LL;
157+
} // current_string->str
158+
kfree(current_string_ptr_str);
159+
kfree(current_string->info);
160+
current_string->str = 0LL;
161+
current_string->info = 0LL;
162+
kfree(current_string);
163+
storages[(int)index_storage____] = 0LL;
164+
}
165+
return len_copied_;
166+
}
167+
return -34LL;
168+
}
169+
if ( (_DWORD)a2 != 16 )
170+
return -11LL;
171+
LODWORD(result) = strncpy_from_user(str_copied, local_buffer, 8LL);
172+
if ( !(_DWORD)result || (_DWORD)result == 9 )
173+
return -34LL;
174+
if ( (int)result < 0 )
175+
return (int)result;
176+
storages__ = storages;
177+
while ( 1 )
178+
{
179+
found_string_ptr_ = *storages__;
180+
if ( *storages__ )
181+
{
182+
if ( !strcmp((const char *)found_string_ptr_->str, str_copied) )
183+
break;
184+
}
185+
if ( ++storages__ == &storages[16] )
186+
return -11LL;
187+
}
188+
v6 = v29;
189+
found_info = (struct pid_len *)found_string_ptr_->info;
190+
found_pid = found_info->pid;
191+
found_size_str = *(_DWORD *)&found_info->size_str;
192+
LODWORD(result) = ((__int64 (__fastcall *)(__int64, __int64, __int32))put_user_size)(0LL, v29, 4);
193+
if ( (_DWORD)result )
194+
return (int)result;
195+
LODWORD(result) = put_user_size(found_pid, v6 + 8);
196+
if ( (_DWORD)result )
197+
return (int)result;
198+
return (int)put_user_size(found_size_str, v6 + 12);
199+
}

0 commit comments

Comments
 (0)