Escriba el comando crash de la extensión del complemento de la herramienta de bloqueo de Linux

La hora actual es alrededor de las 10:45 pm del viernes.

Mi requisito es usar la herramienta de bloqueo para descargar los nombres de los módulos de un cierto punto de enlace de Netfilter.

Mi método es el siguiente, primero encuentre la dirección del módulo:

crash px nf_hooks[2][0] =>var
crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk -F '=' '/owner/{print $2}'

Esto dará como resultado una lista, como:

0x1234
0x6678
0x8641
0x4570
...

Obviamente, estas direcciones son la estructura del módulo, necesito ejecutar el siguiente comando para obtener el campo de nombre:

crash module.name $addr_above

Sin embargo, tengo que ingresar uno por uno, o usar la redirección de archivos:

crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk -F '=' '/owner/{print $2}' >./aa
crash module.name <./aa 

Esto es demasiado problema.

Quiero saber si puedo escribir un script en la línea de comando de bloqueo o usar algo como xargs, awk BEGIN, END, por ejemplo, use lo siguiente:

crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk -F '=' '/owner/{print $2}' | xargs -i    module.name {
    
    }

De esta manera, todos los resultados se obtienen al mismo tiempo, eliminando el problema de la entrada manual.

Lo intenté, pero el comando crash no se puede canalizar.

Después de indagar, me enteré de que crash tiene un comando de extensión para cargar complementos de extensión de extensión. Después de estudiarlo, es relativamente simple y significativo.

Para decirlo sin rodeos, se trata de escribir una biblioteca compartida basada en la API de bloqueo. Si ingresa help extend en la línea de comando de bloqueo, se mostrará cómo se codifican dichas bibliotecas compartidas. Simplemente escribí uno basado en los requisitos anteriores, que se pueden usar:

// nfhooks.c
#include <crash/defs.h>

static int get_field(unsigned long addr, char *name, char *field, void* buf)
{
    
    
	unsigned long off = MEMBER_OFFSET(name, field);

	if (!readmem(addr + off, KVADDR, buf, MEMBER_SIZE(name, field), name, FAULT_ON_ERROR))
		return 0;
	return 1;
}

void do_cmd(void)
{
    
    
	unsigned long ops_addr, owner_addr;
	unsigned long list_addr, base, next;
	char name[64];

	optind++;
	base = next = list_addr = htol(args[optind], FAULT_ON_ERROR, NULL);

	do {
    
    
		// 由于list就是nf_hook_ops的第一个字段,因此就不炫技了,强转即可。
		//get_field(list_addr - MEMBER_OFFSET("nf_hook_ops", "list"), "list_head", "next", &ops_addr);
		ops_addr = list_addr = next;
		get_field(ops_addr, "nf_hook_ops", "owner", &owner_addr);
		get_field(owner_addr, "module", "name", &name[0]);
		if (list_addr != base)
			fprintf(fp, "--%s\n", name);
		} while(get_field(list_addr, "list_head", "next", &next) && next != base);
}

static struct command_table_entry command_table[] = {
    
    
	{
    
     "nfhooks", do_cmd, NULL, 0},
	{
    
     NULL },
};

void __attribute__((constructor)) nfhooks_init(void)
{
    
    
	register_extension(command_table);
}

void __attribute__((destructor)) nfhooks_fini(void) {
    
     }

El comando de compilación es el siguiente:

gcc -fPIC -shared nfhooks.c -o nfhooks.so

Coloque el archivo generado en el directorio donde se ejecuta el comando de bloqueo y cárguelo en la línea de comando de bloqueo:

crash> extend nfhooks.so
./nfhooks.so: shared object loaded

Entonces se puede utilizar:

# 首先dump出INET IPv4的PREROUTING点的list地址
crash> px &nf_hooks[2][0]
$1 = (struct list_head *) 0xffffffff81a71000 <nf_hooks+256>
crash> nfhooks 0xffffffff81a71000
--bridge
--nf_defrag_ipv4
--iptable_raw
--nf_conntrack_ipv4
--iptable_mangle
--iptable_nat
crash>

¿No es interesante?

Con este mecanismo, puede usar readmem fácilmente para analizar cualquier campo de estructura de cualquier dirección en el kernel de Linux. Ya no tiene que quejarse de que el comando crash no es suficiente. Si no es suficiente, escriba uno usted mismo y escriba uno usted mismo. El costo de es muy bajo, nada más que readmem analiza constantemente la estructura, detrás de todo esto, solo necesitas estar familiarizado con el kernel.

Escribí un programa para analizar / dev / mem o vmcore manualmente antes, pero en comparación con la extensión del complemento crash, es demasiado bajo y problemático.Con este mecanismo, ya no hay necesidad de hacer trabajo manual.

Extendiendo un poco el código anterior, puede volcar todas las familias de protocolos y todos los nombres de módulo de todos los puntos de enlace:

#include <crash/defs.h>

static int get_field(unsigned long addr, char *name, char *field, void* buf)
{
    
    
	unsigned long off = MEMBER_OFFSET(name, field);

	if (!readmem(addr + off, KVADDR, buf, MEMBER_SIZE(name, field), name, FAULT_ON_ERROR))
		return 0;
	return 1;
}

#define FAMILY	12
#define TYPE	8

struct dummy_list {
    
    
	struct dummy_list *next, *prev;
};

struct dummy_list *iter;
void do_cmd(void)
{
    
    
	unsigned long ops_addr, owner_addr;
	unsigned long list_addr, base, next;
	char name[64];
	int i, j;

	optind++;
	iter = (struct dummy_list *)htol(args[optind], FAULT_ON_ERROR, NULL);

	for (i = 0; i < FAMILY; i++) {
    
    
		for (j = 0; j < TYPE; j++) {
    
    
			fprintf(fp, "at PF: %d  hooknum: %d \n", i, j);
			base = next = list_addr = (unsigned long)&iter[i*TYPE + j];
			do {
    
    
				ops_addr = list_addr = next;
				get_field(ops_addr, "nf_hook_ops", "owner", &owner_addr);
				get_field(owner_addr, "module", "name", &name[0]);
				if (list_addr != base)
					fprintf(fp, "  ----%s\n", name);
				} while(get_field(list_addr, "list_head", "next", &next) && next != base);
		}
	}
}

static struct command_table_entry command_table[] = {
    
    
	{
    
     "allnfhooks", do_cmd, NULL, 0},
	{
    
     NULL },
};

void __attribute__((constructor)) nfhooks_init(void)
{
    
    
	register_extension(command_table);
}

void __attribute__((destructor)) nfhooks_fini(void) {
    
     }

¿Es muy simple? Nunca grabo cosas complicadas, las simples son realmente hermosas.

La hora actual es alrededor de las 10:45 pm del viernes. Ya no está bajo la jurisdicción de 996, ¡continúe informando!


Los zapatos de cuero en Wenzhou, Zhejiang están mojados, por lo que no engordan con la lluvia.

Supongo que te gusta

Origin blog.csdn.net/dog250/article/details/107997905
Recomendado
Clasificación