逆向-beginners之helloworld

#include <stdio.h>

int _main()
{
    printf("hello world.\n");
    return 0;
}

// 上面的代码等效于:
char *SG3830[] = {"hello, world\n"};

int main()
{
    printf("%s", *SG3830);
    return 0;
}

#if 0
/*
 * intel
 */
0000000000001169 <_main>:
    1169:    f3 0f 1e fa              endbr64
    116d:    55                       push   %rbp
    116e:    48 89 e5                 mov    %rsp,%rbp
    1171:    48 8d 3d 8c 0e 00 00     lea    0xe8c(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>  // rdi="hello world.\n"
    1178:    e8 e3 fe ff ff           callq  1060 <puts@plt>          // puts(rdi)
    117d:    b8 00 00 00 00           mov    $0x0,%eax
    1182:    5d                       pop    %rbp
    1183:    c3                       retq   

0000000000001184 <main>:
    1184:    f3 0f 1e fa              endbr64
    1188:    55                       push   %rbp
    1189:    48 89 e5                 mov    %rsp,%rbp
    118c:    48 8b 05 7d 2e 00 00     mov    0x2e7d(%rip),%rax        # 4010 <SG3830>
    1193:    48 89 c6                 mov    %rax,%rsi                // rsi="hello world.\n"
    1196:    48 8d 3d 82 0e 00 00     lea    0xe82(%rip),%rdi        # 201f <_IO_stdin_used+0x1f> // rdi="%s"
    119d:    b8 00 00 00 00           mov    $0x0,%eax
    11a2:    e8 c9 fe ff ff           callq  1070 <printf@plt>        // printf(rdi, rsi)
    11a7:    b8 00 00 00 00           mov    $0x0,%eax
    11ac:    5d                       pop    %rbp
    11ad:    c3                       retq   
    11ae:    66 90                    xchg   %ax,%ax

/*
 * arm
 */
00000000004005ac <_main>:
  4005ac:    a9bf7bfd     stp    x29, x30, [sp, #-16]!
  4005b0:    910003fd     mov    x29, sp
  4005b4:    90000000     adrp    x0, 400000 <_init-0x428>
  4005b8:    911aa000     add    x0, x0, #0x6a8              // x0="hello world.\n"
  4005bc:    97ffffb5     bl    400490 <puts@plt>           // puts(x0)
  4005c0:    52800000     mov    w0, #0x0                       // #0
  4005c4:    a8c17bfd     ldp    x29, x30, [sp], #16
  4005c8:    d65f03c0     ret

00000000004005cc <main>:
  4005cc:    a9bf7bfd     stp    x29, x30, [sp, #-16]!
  4005d0:    910003fd     mov    x29, sp
  4005d4:    b0000080     adrp    x0, 411000 <__libc_start_main@GLIBC_2.17>
  4005d8:    9100e000     add    x0, x0, #0x38
  4005dc:    f9400001     ldr    x1, [x0]        // x1="hello world.\n"
  4005e0:    90000000     adrp    x0, 400000 <_init-0x428>
  4005e4:    911b2000     add    x0, x0, #0x6c8  // x0="%s"
  4005e8:    97ffffae     bl    4004a0 <printf@plt> // printf(x0, x1)
  4005ec:    52800000     mov    w0, #0x0                       // #0
  4005f0:    a8c17bfd     ldp    x29, x30, [sp], #16
  4005f4:    d65f03c0     ret


#endif

#if 0
/*
 *  intel
 */
    xor eax, eax
    mov eax, 0
    两条指令结果相同,但xor 异或运算的opcode较短。

    也有一些编译器使用 sub eax, eax 把eax置0。

/*
 * gcc
 */
main     proc near
var_10     = dword ptr - 10h

    push ebp
    mov ebp, esp
    and esp, fffffff0    # 令栈地址(ESP的值)向16字节边界对齐(成为16的整数倍)
    sub esp, 10
    mov eax, offset HelloWord    ; "hello, world\n"字符串在数据段地址(指针)存储到EAX
    mov [esp+10+var_10], eax    ; 再把它存储在数据栈里
    call _printf
    mov eax, 0
    leave
    retn

main endp

    如钩地址位没有对齐,那么CPU可能需要访问两次内存才能获得栈内数据。

    sub esp, 10    在栈中分配0x10 bytes,即16字节。程序只会用到4字节空间。但是因为
编译器对栈地址(ESP)进行了16字节对齐,所以每次都会分配16字节的空间。

    leave 指令,等效于“MOV ESP, EBP” 和 “POP EBP” 两条指令。


/*
 * X86-64
 */
    SG2989 db  'hello, world', 00h

    main proc
        sub rsp, 40
        lea rcx, offset flat:SG2989
        call printf
        xor eax, eax
        add rsp, 40
        ret 0
    main endp

    main函数的返回值是整数类型的零,但是出于兼容性和可移植性的考虑,C语言的编译器仍将使用32位的零。换而言之,即使是64位的
    应用程序,在程序结束时EAX的值是零,而RAX的值不一定会是零。

    此时,数据栈的对应空间里仍有40字节的数据。这部分数据空间有个专用的名词,即阴影空间(shadow space)。


/*
 * gcc x86-64
 */
    .string "hello,world\n"
    main:
        sub rsp, 8
        mov edi, offset flat:.LC0    ; hello,world
        xor eax, eax                ; number of vector registers passed
        call printf
        xor eax, eax
        add rsp, 8
        ret

    需要注意的是,64位汇编指令MOV在写放R-寄存器的低32位地址位的时候即对E-寄存器进行写操作的时候,会同时清除R-寄存器中的高32位地址
    位。

/*
 * arm
 */
    main
        stmfd sp!, {r4, lr}
        aor ro, aHellowWorld    ; "hello, world"
        bl _2printf
        mov r0, #0
        ldmfd sp!, {r4, pc}

/*
 * arm 64
 */
    stp x29, x30, [sp, #-16]!
    mov x29, sp
    adrp x0, 40000<_init+0x3b8>
    add x0, x0, #0x648
    bl 40040 <puts@plt>
    mov wo, #0x0
    ldp x29, x30, [sp], #16
    ret

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值