.dtors parece gravável, mas tenta gravar segfault


9

Este é o Ubuntu 9.04, 2.6.28-11-server, 32bit x86


$ cat test.c
main() { int *dt = (int *)0x08049f18; *dt = 1; }
$ readelf -S ./test
...
  [18] .dtors            PROGBITS        08049f14 000f14 000008 00  WA  0   0  4
...
$ ./test
Segmentation fault
$

Para os não iniciados: gcc cria um segmento destruidor .dtors, no executável elf, chamado após main()saídas. Esta tabela tem sido gravável e parece que deveria estar no meu caso (consulte a readelfsaída). Mas tentar gravar na tabela causa um segfault.

Sei que tem havido um movimento em direção a médicos, somente leitura, recentemente, mas o que não entendo é a incompatibilidade entre o readelfe o segfault.


A verdadeira questão é por que você deseja que seja gravável?
25411 alex

11
Estou dando uma aula de segurança que envolve a quebra de uma série de programas vulneráveis, mas um exercício envolve escrever em .dtors em exec shellcode. Não funciona mais e estou tentando rastrear o problema.
Fixee

A incompatibilidade ocorre porque provavelmente existem algumas realocações de dados (que precisam ser corrigidas antes de marcar somente leitura, e não podem ser preguiçosas de qualquer maneira, portanto serão constantes após a correção) lá.
Ninjalj

Respostas:


5

Essas seções são marcadas como GNU_RELRO (realocações somente leitura), o que significa que, assim que o carregador dinâmico for consertado (no momento do carregamento, não houver realocações preguiçosas), todas as relocações serão marcadas como somente leitura. Observe que a maioria .got.pltestá em outra página, portanto não recebe o tratamento.

Você pode ver o script do vinculador ld --verbose, se procurar por RELRO, encontrará algo semelhante a:

.got            : { *(.got) }
. = DATA_SEGMENT_RELRO_END (12, .);
.got.plt        : { *(.got.plt) }

o que significa que as seções RELRO terminam com 12 bytes .got.plt(os ponteiros para as funções do vinculador dinâmico já estão resolvidos e podem ser marcados como somente leitura).

O projeto Gentoo reforçado possui alguma documentação sobre o RELRO em http://www.gentoo.at/proj/en/hardened/hardened-toolchain.xml#RELRO .


5

Eu posso dizer por que está falhando, embora eu realmente não saiba qual parte do sistema é responsável. Embora .dtorsesteja marcado como gravável no binário, parece que ele (junto com .ctorso GOT e algumas outras coisas) está sendo mapeado em uma página separada, não gravável na memória. No meu sistema, .dtorsestá sendo colocado em 0x8049f14:

$ readelf -S test
  [17] .ctors            PROGBITS        08049f0c 000f0c 000008 00  WA  0   0  4
  [18] .dtors            PROGBITS        08049f14 000f14 000008 00  WA  0   0  4
  [19] .jcr              PROGBITS        08049f1c 000f1c 000004 00  WA  0   0  4
  [20] .dynamic          DYNAMIC         08049f20 000f20 0000d0 08  WA  6   0  4
  [21] .got              PROGBITS        08049ff0 000ff0 000004 04  WA  0   0  4
  [22] .got.plt          PROGBITS        08049ff4 000ff4 00001c 04  WA  0   0  4
  [23] .data             PROGBITS        0804a010 001010 000008 00  WA  0   0  4
  [24] .bss              NOBITS          0804a018 001018 000008 00  WA  0   0  4

Se eu executar o executável e verificar /proc/PID/maps, vejo:

08048000-08049000 r-xp 00000000 08:02 163678     /tmp/test
08049000-0804a000 r--p 00000000 08:02 163678     /tmp/test
0804a000-0804b000 rw-p 00001000 08:02 163678     /tmp/test

.data/ .bssainda são graváveis ​​em sua própria página, mas os outros 0x8049000-0x804a000não. Eu assumo que este é um recurso de segurança no kernel (como você disse, "houve um movimento em direção a somente .dtors, plt, recentemente)", mas não sei especificamente o que é chamado (o OpenBSD tem algo muito semelhante chamado W ^ X ; o Linux possui PaX , mas não está embutido na maioria dos kernels)

Você pode contornar isso mprotect, o que permite alterar os atributos na memória de uma página:

mprotect((void*)0x8049000, 4096, PROT_WRITE);

Com isso, meu programa de teste não falha, mas se eu tentar sobrescrever o sentinela final de .dtors( 0x8049f18) pelo endereço de outra função, essa função ainda não será executada; essa parte eu não consigo descobrir.

Espero que alguém saiba o que é responsável por tornar a página somente leitura e por que modificar .dtorsnão parece fazer nada no meu sistema


3
Se o OP Linux com PaX mprotectnão puder tornar uma página executável gravável ou executável antes, a menos que esse recurso esteja desativado paxctl -m.
23411 stribika

@stribika Ah, bom saber
Michael Mrozek
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.