2

.datax86-64 arch で位置に依存しない方法で sectionから変数にアクセスできる GAS 構文を使用して、 32 ビットarch と IS (%eipの代わりに) を適用するアセンブリ プログラムを作成しようとしています%rip

どのレジスタを試しても、得られた最良の結果は であり、Segmentation fault: 11それでさえ、まったく実行できないはずの EIP、つまり SF にアクセスするためのものでした。少なくとも「まあ、それはうまくいかない」以外のことを教えてくれたので、最良の結果です。

私はgccmacOS 10.13.6 mid 2010 Intel Core 2 Duo でファイルをコンパイルしています (それがclangおそらく理由です):

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

これを使用して、いくつかのオプションをリンカーに渡します。

gcc -m32 -Wl,-fatal_warnings,-arch_errors_fatal,-warn_commons,-pie test.s

ld: 警告: PIE が無効になっています。絶対アドレス指定 (おそらく -mdynamic-no-pic) は、コード署名された PIE では許可されていませんが、/whatever.../test-a07cf9.o の _main で使用されています。この警告を修正するには、-mdynamic-no-pic を使用してコンパイルしたり、-Wl、-no_pie を使用してリンクしたりしないでください。ld: 致命的な警告によってエラーが発生しました (-fatal_warnings)。 -v 呼び出しを表示します) 1


test.s

.text
.global _main

_main:
    xor %eax, %eax
    xor %ebx, %ebx

    # lea var1(%esi/edi/ebp/esp), %ebx  # can't compile, not PIE
    # lea var1(%eip), %ebx  # segfault, obvs

    # lea (%esp), %ebx      # EBX = 17
    # lea (%non-esp), %ebx  # segfault

    # lea 0(%esi), %ebx     # segfault 
    # lea 0(%edi), %ebx     # segfault
    # lea 0(%ebp), %ebx     # EBX = 0
    # lea 0(%esp), %ebx     # EBX = 17
    # lea 0(%eip), %ebx     # segfault, obvs

    movl (%ebx), %eax
    ret

.data
    var1: .long 6

.end

./a.out; echo $?最後からEAX値を確認するために実行していますret

さまざまな情報源を調べましたが、ほとんどはインテルの構文またはこれらの質問の123です。私が思いついた最も単純なCの例、つまりグローバル変数 +returnからmain()-を逆アセンブルしようとしましたgcc -S test.c -fPIE -pie -fpie -m32:

int var1 = 6;
int main() { return var1; }

基本的に次の結果になりました。

    .section    __TEXT,__text,regular,pure_instructions
    .macosx_version_min 10, 13
    .globl  _main                   ## -- Begin function main
    .p2align    4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushl   %ebp
Lcfi0:
    .cfi_def_cfa_offset 8
Lcfi1:
    .cfi_offset %ebp, -8
    movl    %esp, %ebp
Lcfi2:
    .cfi_def_cfa_register %ebp
    pushl   %eax
    calll   L0$pb
L0$pb:
    popl    %eax
    movl    $0, -4(%ebp)
    movl    _var1-L0$pb(%eax), %eax
    addl    $4, %esp
    popl    %ebp
    retl
    .cfi_endproc
                                        ## -- End function
    .section    __DATA,__data
    .globl  _var1                   ## @var1
    .p2align    2
_var1:
    .long   6                       ## 0x6


.subsections_via_symbols

これは明らかにMOVをLEAとして使用し、私のものとほぼ同じ命令を使用しますが、セクションに入るために-L0$pb+/-のようなアドレスの_var1-アドレスの部分を除きます。L0$pb.data

var1それでも、_mainラベルと同じアプローチを試してみると、何もありません:

.text
.global _main

_main:
    xor %eax, %eax
    xor %ebx, %ebx

    #movl var1-_main(%ebp), %eax  # EAX = 191
    #movl var1-_main(%esp), %eax  # EAX = 204
    #movl var1-_main(%eax), %eax  # segfault
    ret

.data
    var1: .long 6

.end

私が間違っていることは何ですか?

編集:

逆アセンブルされた C の例から不要なものを切り取り、最終的には次のようになりました。

.text
.global _main

_main:
    pushl %ebp
    pushl %eax
    calll test

test:
    popl %eax

    /* var1, var2, ... */
    movl var1-test(%eax), %eax

    addl $4, %esp
    popl %ebp
    retl

/**
 * how var1(label) - test(label) skips this label
 * if it's about address subtracting?
 */
blobbbb:
    xor %edx, %edx

.data
var1: .long 6
var2: .long 135

このガイドによると、呼び出し元は 1) パラメータをスタックにプッシュする (なし) 2)callラベルと呼び出し先は実際に ESP、EBP、およびその他のレジスタを操作する必要があるため、私にはあまり意味がありません。また、なぜ中間のラベルが必要なのか、もっと言えば、それなしで方法はありますか?

4

1 に答える 1