@@ -48,36 +48,44 @@ void speakeasy_set_shellcode_dir(const char *dir)
4848 shellcode_dir = g_strdup (dir );
4949}
5050
51+ // SHA256 hex string is always 64 chars + null
52+ #define SHA256_HEX_SIZE 65
53+ // Max path: dir + "/shellcode-" + 64 hex chars + ".bin"/".txt" + null
54+ #define SHELLCODE_PATH_MAX 512
55+
5156/**
52- * Compute SHA256 hash of data and return as hex string
53- * Caller must free the returned string with g_free()
57+ * Compute SHA256 hash of data and write hex string into caller-provided buffer
58+ * Buffer must be at least SHA256_HEX_SIZE (65) bytes
59+ * Returns true on success, false on failure
5460 */
55- static char * compute_sha256_hex (const void * data , size_t len )
61+ static bool compute_sha256_hex (char * hex , size_t hex_size , const void * data , size_t len )
5662{
5763 unsigned char hash [EVP_MAX_MD_SIZE ];
5864 unsigned int hash_len ;
5965
66+ if (hex_size < SHA256_HEX_SIZE )
67+ return false;
68+
6069 EVP_MD_CTX * ctx = EVP_MD_CTX_new ();
6170 if (ctx == NULL ) {
62- return NULL ;
71+ return false ;
6372 }
6473
6574 if (EVP_DigestInit_ex (ctx , EVP_sha256 (), NULL ) != 1 ||
6675 EVP_DigestUpdate (ctx , data , len ) != 1 ||
6776 EVP_DigestFinal_ex (ctx , hash , & hash_len ) != 1 ) {
6877 EVP_MD_CTX_free (ctx );
69- return NULL ;
78+ return false ;
7079 }
7180 EVP_MD_CTX_free (ctx );
7281
7382 // Convert to hex string
74- char * hex = g_malloc (hash_len * 2 + 1 );
7583 for (unsigned int i = 0 ; i < hash_len ; i ++ ) {
7684 snprintf (hex + i * 2 , 3 , "%02x" , hash [i ]);
7785 }
7886 hex [hash_len * 2 ] = '\0' ;
7987
80- return hex ;
88+ return true ;
8189}
8290
8391/**
@@ -97,33 +105,37 @@ static bool save_shellcode(const void *data, size_t len, int offset,
97105 return false;
98106 }
99107
100- char * sha256 = compute_sha256_hex ( data , len ) ;
101- if (sha256 == NULL ) {
108+ char sha256 [ SHA256_HEX_SIZE ] ;
109+ if (! compute_sha256_hex ( sha256 , sizeof ( sha256 ), data , len ) ) {
102110 g_warning ("Failed to compute SHA256" );
103111 return false;
104112 }
105113
106- // Build file paths
107- char * bin_path = g_strdup_printf ("%s/shellcode-%s.bin" , shellcode_dir , sha256 );
108- char * txt_path = g_strdup_printf ("%s/shellcode-%s.txt" , shellcode_dir , sha256 );
114+ // Build file paths on stack
115+ char bin_path [SHELLCODE_PATH_MAX ];
116+ char txt_path [SHELLCODE_PATH_MAX ];
117+ int n = snprintf (bin_path , sizeof (bin_path ), "%s/shellcode-%s.bin" , shellcode_dir , sha256 );
118+ if (n < 0 || (size_t )n >= sizeof (bin_path )) {
119+ g_warning ("Shellcode bin path too long" );
120+ return false;
121+ }
122+ n = snprintf (txt_path , sizeof (txt_path ), "%s/shellcode-%s.txt" , shellcode_dir , sha256 );
123+ if (n < 0 || (size_t )n >= sizeof (txt_path )) {
124+ g_warning ("Shellcode txt path too long" );
125+ return false;
126+ }
109127
110128 // Check if already exists (dedup by hash)
111129 struct stat st ;
112130 if (stat (bin_path , & st ) == 0 ) {
113131 g_debug ("Shellcode %s already saved" , sha256 );
114- g_free (sha256 );
115- g_free (bin_path );
116- g_free (txt_path );
117132 return true;
118133 }
119134
120135 // Save binary data
121136 FILE * f = fopen (bin_path , "wb" );
122137 if (f == NULL ) {
123138 g_warning ("Failed to open %s for writing" , bin_path );
124- g_free (sha256 );
125- g_free (bin_path );
126- g_free (txt_path );
127139 return false;
128140 }
129141 size_t written = fwrite (data , 1 , len , f );
@@ -132,9 +144,6 @@ static bool save_shellcode(const void *data, size_t len, int offset,
132144 if (written != len ) {
133145 g_warning ("Failed to write shellcode data" );
134146 unlink (bin_path );
135- g_free (sha256 );
136- g_free (bin_path );
137- g_free (txt_path );
138147 return false;
139148 }
140149
@@ -166,9 +175,6 @@ static bool save_shellcode(const void *data, size_t len, int offset,
166175
167176 g_info ("Saved shellcode %s.bin (%zu bytes, %s)" , sha256 , len , arch );
168177
169- g_free (sha256 );
170- g_free (bin_path );
171- g_free (txt_path );
172178 return true;
173179}
174180
@@ -484,14 +490,14 @@ void proc_speakeasy_on_io_in(struct connection *con, struct processor_data *pd)
484490 // All architectures now use execution-based validation to reduce false positives
485491
486492 // x86-32 uses libemu for emulation-based detection
487- struct emu * e = emu_new ();
488493 if ( size <= 0 )
489494 {
490495 g_debug ("No data to scan (size=%d)" , size );
496+ g_free (streamdata );
491497 return ;
492498 }
493- uint16_t scan_size = ( size > UINT16_MAX ) ? UINT16_MAX : ( uint16_t ) size ;
494- int ret_x86 = emu_shellcode_test_x86 (e , streamdata , scan_size );
499+ struct emu * e = emu_new () ;
500+ int ret_x86 = emu_shellcode_test_x86 (e , streamdata , ( uint32_t ) size );
495501 emu_free (e );
496502
497503 // x86-64 still uses pattern-based detection (TODO: add execution validation)
0 commit comments