Ilk eBPF Programi ve Tracepoint'ler

Reading syscall arrays

Önceki alıştırmada, execve system call’ından filename argument’ini ctx->args[0] kullanarak nasıl okuyacağınızı öğrendiniz.

Şimdi ikinci argument’i keşfedelim: argv. Şu şekilde bir komut çalıştırdığınızda:

./secret_app --password hunter2

Kernel bir argument dizisi alır:

  • argv[0] = "./secret_app"
  • argv[1] = "--password"
  • argv[2] = "hunter2"
  • argv[3] = NULL (sonlandırıcı)

execve manual sayfasına baktığımızda:

int execve(const char *filename, char *const argv[], char *const envp[]);

İkinci parametre olan argv, ctx->args[1] konumundadır.

Bir string’e basit bir pointer olan filename’den farklı olarak, argv ve envp pointer dizisine işaret eden pointer’lardır.

args[0]char* filenameargs[1]char* argv[]args[2]char* envp[]secret_app…argv[0]./secret_ap…argv[1]--password\0argv[2]hunter2\0NULLenvp[0]PATH=/usr/b…envp[1]HOME=/homeNULL

Diyagramda gördüğünüz gibi, argv ve envp bir NULL pointer ile sonlandırılır.

argv dizisinden bir girdi okuduğunuzda (örneğin argv[i]), kullanmadan önce NULL olup olmadığını kontrol edin, çünkü bu dizinin sonunu işaretler.

Pointer dizisini okuma

argv’yi okumak için şu adımları izlememiz gerekiyor:

  1. ctx->args[1]’den argv pointer’ını alın
  2. unsigned long’dan char ** tipine cast edin
  3. Dizideki her pointer’ı okuyun (user space’den)
  4. Her pointer için, işaret ettiği string’i okuyun (yine user space’den)

Temel yapı şöyledir:

// Get the argv pointer
char **argv = (char **)ctx->args[1];

// In a loop, read the next pointer from the array
char *arg_ptr;
bpf_probe_read_user(&arg_ptr, sizeof(arg_ptr), &argv[i]);
// Remember to check for the NULL terminator!

// Read the string that pointer points to
char arg_buf[64];
bpf_probe_read_user_str(arg_buf, sizeof(arg_buf), arg_ptr);

Döngünün sabit bir üst sınırı olması gerektiğini unutmayın (örneğin i < 10), çünkü verifier programınızın sonlanacağını kanıtlaması gerekir.

Görev

Şüpheli bir program --password flag’i ve ardından gerçek parola ile çalıştırılıyor.

Yapmanız gerekenler:

  1. argv dizisi üzerinde yineleyin (yinelemeyi 10 argument ile sınırlayın)
  2. "--password" içeren argument’i bulun
  3. Gerçek parolayı içeren sonraki argument’i okuyun
  4. SUBMIT_STR_LEN ile gönderin
Quick reference
Compare two strings for equality
Function bpf_strncmp Full documentation
Args:
char* bufdynamic buffer to compare
u32 buf_szlength of dynamic buffer
const char* buf2literal string to compare against
Returns 0 if strings match, non-zero if they differ
Read string from user space into kernel buffer
Function bpf_probe_read_user_str Full documentation
Args:
void* dstkernel buffer to read into
u32 sizemaximum bytes to read
const void* srcuser space pointer to string
On success, returns number of bytes read (including null terminator)
On error, returns negative error code
Read bytes from user space into kernel buffer
Function bpf_probe_read_user Full documentation
Args:
void* dstkernel buffer to read into
u32 sizebytes to read
const void* srcuser space pointer
On success, returns 0
On error, returns negative error code
Run your code to see execution events here