119 lines
2.6 KiB
C
119 lines
2.6 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define LIBSSH2_PACKET_MAXPAYLOAD 35000u
|
|
|
|
struct target_object {
|
|
unsigned char payload[19];
|
|
void (*callback)(const char *);
|
|
char command[320];
|
|
};
|
|
|
|
static void safe_callback(const char *command)
|
|
{
|
|
printf("safe_callback command=%s\n", command);
|
|
}
|
|
|
|
static void exec_callback(const char *command)
|
|
{
|
|
int rc;
|
|
|
|
printf("exec_callback command=%s\n", command);
|
|
fflush(stdout);
|
|
rc = system(command);
|
|
printf("system_rc=%d\n", rc);
|
|
}
|
|
|
|
static int read_exact(unsigned char *buf, size_t len)
|
|
{
|
|
size_t got = fread(buf, 1, len, stdin);
|
|
return got == len ? 0 : -1;
|
|
}
|
|
|
|
static uint32_t load_be32(const unsigned char *buf)
|
|
{
|
|
return ((uint32_t)buf[0] << 24) |
|
|
((uint32_t)buf[1] << 16) |
|
|
((uint32_t)buf[2] << 8) |
|
|
(uint32_t)buf[3];
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
unsigned char hdr[8];
|
|
unsigned char *body = NULL;
|
|
struct target_object *obj = NULL;
|
|
uint32_t packet_length;
|
|
uint32_t body_len;
|
|
unsigned int auth_len = 16;
|
|
int mac_len = 0;
|
|
size_t total_num = 4;
|
|
size_t copy_len;
|
|
|
|
obj = (struct target_object *)calloc(1, sizeof(*obj));
|
|
if(!obj) {
|
|
return 1;
|
|
}
|
|
|
|
obj->callback = safe_callback;
|
|
strcpy(obj->command, "not executed");
|
|
|
|
printf("LEAK exec_callback=%p callback_offset=%zu command_offset=%zu ptr_size=%zu\n",
|
|
(void *)exec_callback,
|
|
offsetof(struct target_object, callback),
|
|
offsetof(struct target_object, command),
|
|
sizeof(void *));
|
|
fflush(stdout);
|
|
|
|
if(read_exact(hdr, sizeof(hdr))) {
|
|
free(obj);
|
|
return 2;
|
|
}
|
|
|
|
packet_length = load_be32(hdr);
|
|
body_len = load_be32(hdr + 4);
|
|
|
|
if(packet_length < 1u) {
|
|
free(obj);
|
|
return 3;
|
|
}
|
|
|
|
total_num += packet_length + (mac_len ? mac_len : 0) + auth_len;
|
|
|
|
if(total_num > LIBSSH2_PACKET_MAXPAYLOAD || total_num == 0u) {
|
|
free(obj);
|
|
return 4;
|
|
}
|
|
|
|
body = (unsigned char *)malloc(body_len ? body_len : 1);
|
|
if(!body) {
|
|
free(obj);
|
|
return 5;
|
|
}
|
|
|
|
if(read_exact(body, body_len)) {
|
|
free(body);
|
|
free(obj);
|
|
return 6;
|
|
}
|
|
|
|
copy_len = packet_length - 1u;
|
|
if(copy_len > body_len) {
|
|
copy_len = body_len;
|
|
}
|
|
|
|
printf("accepted packet_length=0x%08x allocation=%zu copy_len=%zu body_len=%u\n",
|
|
packet_length, total_num, copy_len, body_len);
|
|
fflush(stdout);
|
|
|
|
memcpy(obj->payload, body, copy_len);
|
|
obj->callback(obj->command);
|
|
|
|
free(body);
|
|
free(obj);
|
|
return 0;
|
|
}
|