Arbitrary payload modification fully works now. Absolutely ridicous the time it took me (2 days) to realize I was computing the ip checksum with the old checksum values, which made it not to work. Finally can keep going

This commit is contained in:
h3xduck
2021-11-27 14:10:43 -05:00
parent ca23880fd4
commit a440326653
7 changed files with 814 additions and 802 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -122,6 +122,7 @@ int xdp_receive(struct xdp_md *ctx)
bpf_printk("OLD data_end: %i, payload: %i\n", data_end, payload);
struct expand_return ret = expand_tcp_packet_payload(ctx, eth, ip, tcp, 2);
bpf_printk("Control back to main program with retcode %i\n", ret.code);
if(ret.code == 0){
//We must check bounds again, otherwise the verifier gets angry
ctx = ret.ret_md;
@@ -156,14 +157,14 @@ int xdp_receive(struct xdp_md *ctx)
//Quite a trick to avoid the verifier complaining when it's clear we are OK with the payload
//Line 6367 https://lxr.missinglinkelectronics.com/linux/kernel/bpf/verifier.c
if(payload_size < 0|| payload_size>88888){
bpf_printk("exploding heavily\n");
bpf_printk("Unlikely you are here, but OK\n");
return XDP_PASS;
}
if(payload_size -1 < data_end - (void*)payload ){
/*if(payload_size -1 < data_end - (void*)payload ){
return XDP_PASS;
}
}*/
//Revise this, the idea is to use payload_size, but th everifier keeps thinking it will go out of bounds
//Revise this, the idea is to use payload_size, but the verifier keeps thinking it will go out of bounds
//Also, note that sizeof(..) is returning strlen +1, but it's ok because
//we do not want to write at payload[6]
if((void*)payload + sizeof(SECRET_PACKET_PAYLOAD) +1 > data_end){
@@ -176,7 +177,8 @@ int xdp_receive(struct xdp_md *ctx)
return XDP_PASS;
}
char* temp_data = (char*)payload;
payload[5] = 'a';
payload[4] = 'a';
payload[5] = '\0';
bpf_printk("BPF finished with ret %i and payload %s of size %i\n ", ret.code, payload, payload_size);
}else{
@@ -185,7 +187,7 @@ int xdp_receive(struct xdp_md *ctx)
data_len_next = data_end-data;
bpf_printk("Previous length: %i, current length: %i\n", data_len_prev, data_len_next);
bpf_printk("NEW data_end: %i, payload: %i\n", data_end, payload);
bpf_printk("And on NEW CTX data_end: %i, payload: %i\n", ctx->data_end);
bpf_printk("And on NEW CTX data_end: %i, payload: %i\n", ctx->data_end, payload);
char payload_to_write[] = "hello";
/*if (tcp_payload_bound_check(payload, payload_size, data_end)){

View File

@@ -24,7 +24,7 @@ static __always_inline unsigned short checksum(unsigned short *addr, int nbytes)
if(nbytes>0){
sum +=htons((unsigned char)*addr);
}
while (sum>>16){
sum = (sum & 0xffff) + (sum >> 16);
}
@@ -34,30 +34,34 @@ static __always_inline unsigned short checksum(unsigned short *addr, int nbytes)
}
static __always_inline uint16_t csum_fold_helper(uint32_t csum)
static __always_inline __u16 csum_fold_helper(__u32 csum)
{
bpf_printk("csumA: %u\n", csum & 0xffff);
bpf_printk("csumB: %u\n", csum >> 16);
bpf_printk("csumA+B: %u\n", (csum & 0xffff) + (csum >> 16));
bpf_printk("csumNEG(A+B): %u\n", ~((csum & 0xffff) + (csum >> 16)));
//return ~((csum & 0xffff) + (csum >> 16));
//The following solves some errors where the last summatory overflows
#pragma unroll
for (int ii = 0; ii < 4; ii++) {
if (csum >> 16)
csum = (csum & 0xffff) + (csum >> 16);
for (int i = 0; i < 4; i ++) {
if (csum >> 16){
csum = (csum & 0xffff) + (csum >> 16);
}
}
return ~csum;
return ~csum;
}
/**
* IP checksum calculation.
* Following RFC 1071, using BPFs.*
*/
static __always_inline void ipv4_csum(void *data_start, int data_size, uint32_t *csum)
static __always_inline void ipv4_csum(void *data_start, int data_size, __u32 *csum)
{
bpf_printk("csum: %u\n", *csum);
*csum = bpf_csum_diff(0, 0, data_start, data_size, *csum);
bpf_printk("csum: %u\n", *csum);
//WITH EBPF HELPERS
bpf_printk("csum: %u for data_start %u, data_size %i\n", *csum, data_start, data_size);
unsigned char* p = (unsigned char*) data_start;
for(int ii = 0; ii<20; ii++){
bpf_printk("B%i: %x\n", ii, p[ii]);
}
*csum = bpf_csum_diff(0, 0, data_start, data_size, *csum);
*csum = csum_fold_helper(*csum);
bpf_printk("csum: %u\n", *csum);
}
#endif

View File

@@ -85,7 +85,8 @@ static __always_inline struct expand_return expand_tcp_packet_payload(struct xdp
//We modify the fields we care about of the headers
bpf_printk("before: %i, checksum %u\n", ret.ip->tot_len, ret.ip->check);
ret.ip->tot_len = htons(ntohs(ret.ip->tot_len) + more_bytes);
uint32_t csum = 0;
__u32 csum = 0;
ret.ip->check = 0;
ipv4_csum(ret.ip, sizeof(struct iphdr), &csum);
ret.ip->check = csum;
bpf_printk("after: %i, checksum %u\n", ret.ip->tot_len, ret.ip->check);
@@ -96,4 +97,8 @@ static __always_inline struct expand_return expand_tcp_packet_payload(struct xdp
return ret;
}
#endif