前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动态调试elf文件的几种方法

动态调试elf文件的几种方法

作者头像
鸿鹄实验室
发布2022-05-27 13:54:28
2.6K0
发布2022-05-27 13:54:28
举报
文章被收录于专栏:鸿鹄实验室鸿鹄实验室

动态调试elf文件的几种方法

最近在刷题的时候遇到了很多elf文件,虽然可以通过ida分析伪代码解出来,但是发现有些通过动态调试的方式可以直接找到flag,这样简单了不少,因为之前接触的linux下的逆向题目比较少,所以通过这次刷题也记录一下动态调试elf文件的几种方式。

0x01 ida动态调试

ida不光可以静态分析函数伪代码,也可以通过动态调试的方式来分析linux下的elf文件。

首先将ida/dbgsrv/路径下的linux_server/linux_serverx64文件复制到linux下,两个文件分别是调试32位和64位程序使用的:

在linux下启动对应的文件:

把我们要调试的文件放到相应的文件夹中,这里我放到/homt/test/文件夹中。

在ida中选择Debugger-Run-Remote linux debugger

在弹出的对话框中,Application填写文件存放的位置和文件名,Directory中填写文件存放的路径,Parameters是指传递的参数,如果程序运行需要传参的话可以在这填入,Hostname就是linux的ip地址,Port一般都是默认的23946,如果设置了password在下方填入,没有就空着:

进入ida动态调试界面,默认情况下界面大概分为6个区域(通用寄存器和标志寄存器窗口为1个),模块列表和线程列表我不怎么看,主要是看反汇编和寄存器还有堆栈。

ida在动态调试的时候和OD差不多,F9继续运行,F7步入,F8步过,F2下断点。

通过Debugger-Breakpoints-Breakpoint list或者Ctrl+Alt+B来查看已经下的断点:

也可以通过Debugger-Debugger windows-Stack trace或者Ctrl+Alt+S查看是谁调用了当前的函数:

虽然感觉没有OD好用,但是实现简单的调试还是没有问题的。

0x02 gdb动态调试

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。

一般在kali中,gdb都是默认安装的。

使用gdb调试可执行文件

代码语言:javascript
复制
gdb <program>    //启动
quit             //结束

运行程序

代码语言:javascript
复制
run:简写为r,运行调试程序,直到断点处
stepi:简写为s,执行一条指令,步入函数
nexti:简写为n,执行一条指令,步过函数
continue:简写为c,继续执行
until:在一个循环体内部单步跟踪的时候,可以通过until命令跳出循环
until+行号:运行至某行

断点

代码语言:javascript
复制
break *address:简写b *address,设置断点
info breakpoints:简写为info b,查看断点
delete *address:删除断点
disable *address:暂停断点
enable *address:开启断点
delete breakpoints:删除所有断点

查看

代码语言:javascript
复制
info register:简写为info r,查看寄存器
x/countFormatSize addr:以指定格式Format打印地址address处的指定大小size、指定数量count的对象
                        Size:b(字节)、h(半字)、w(字)、g(8字节)
                        Format:o(八进制)、d(十进制)、x(十六进制)、u(无符号十进制)、t(二进制)、f(浮点数)、a(地                                址)、i(指令)、c(字符)、s(字符串)
backtrace:打印函数调用栈回溯
set $reg=value:修改寄存器
set *(type*)(address)=value:修改内存地址addr为value

我在使用的过程中大概用到的就是这些命令。

0x03 radare2动态调试

radare2是一个开源项目,他可以使用命令直接执行,也有GUI程序叫做Cutter并且兼容多平台。

在kali中r2也是默认安装的,可以直接在控制台运行,进入程序后使用aaa命令分析程序

代码语言:javascript
复制
$ r2 ./e3dd9674429f4ce1a25c08ea799fc027  
[0x00400660]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.

也可以直接使用r2 -A ./program来直接分析程序

代码语言:javascript
复制
$ r2 -A ./e3dd9674429f4ce1a25c08ea799fc027                                                                                                                                        
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.

在分析程序之前,r2的iI命令可以提供很多有用的信息

代码语言:javascript
复制
[0x00400660]> iI
arch     x86
baddr    0x400000
binsz    9449
bintype  elf
bits     64
canary   true
class    ELF64
compiler GCC: (Ubuntu 5.4.1-2ubuntu1~14.04) 5.4.1 20160904 GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
crypto   false
endian   little
havecode true
intrp    /lib64/ld-linux-x86-64.so.2
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  AMD x86-64 architecture
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      false
relocs   true
relro    partial
rpath    NONE
sanitiz  false
static   false
stripped false
subsys   linux
va       true

在了解程序的基本信息后你还可以通过iiiE命令来看下程序的导入和导出函数,从而能够更好的了解程序实现的功能

代码语言:javascript
复制
[0x00400660]> ii
[Imports]
nth vaddr      bind   type   lib name
―――――――――――――――――――――――――――――――――――――
1   0x004005c0 GLOBAL FUNC       remove
2   0x004005d0 GLOBAL FUNC       fclose
3   0x004005e0 GLOBAL FUNC       strlen
4   0x004005f0 GLOBAL FUNC       __stack_chk_fail
5   0x00400600 GLOBAL FUNC       fputc
6   0x00400610 GLOBAL FUNC       __libc_start_main
7   0x00400620 GLOBAL FUNC       fprintf
8   0x00400630 WEAK   NOTYPE     __gmon_start__
9   0x00400640 GLOBAL FUNC       fseek
10  0x00400650 GLOBAL FUNC       fopen

[0x00400660]> iE
[Exports]

nth paddr       vaddr      bind   type   size lib name
――――――――――――――――――――――――――――――――――――――――――――――――――――――
45   0x00000960 0x00400960 GLOBAL FUNC   2        __libc_csu_fini
49   0x000010e0 0x006010e0 GLOBAL OBJ    44       t
50   ---------- 0x0060120c GLOBAL NOTYPE 0        _edata
51   0x00001160 0x00601160 GLOBAL OBJ    172      p
53   0x00000964 0x00400964 GLOBAL FUNC   0        _fini
58   0x00001080 0x00601080 GLOBAL NOTYPE 0        __data_start
61   0x00001088 0x00601088 GLOBAL OBJ    0        __dso_handle
62   0x00000970 0x00400970 GLOBAL OBJ    4        _IO_stdin_used
63   0x000008f0 0x004008f0 GLOBAL FUNC   101      __libc_csu_init
64   ---------- 0x00601210 GLOBAL NOTYPE 0        _end
65   0x00000660 0x00400660 GLOBAL FUNC   0        _start
67   0x000010a0 0x006010a0 GLOBAL OBJ    33       s
68   0x00001120 0x00601120 GLOBAL OBJ    44       u
69   ---------- 0x0060120c GLOBAL NOTYPE 0        __bss_start
70   0x00000756 0x00400756 GLOBAL FUNC   407      main
73   ---------- 0x00601210 GLOBAL OBJ    0        __TMC_END__
75   0x00000590 0x00400590 GLOBAL FUNC   0        _init

你还可以通过afl命令查看程序存在的函数,从而找到main函数,定位到对应的位置,查看反汇编代码

代码语言:javascript
复制
[0x00400660]> afl
0x00400660    1 41           entry0
0x00400610    1 6            sym.imp.__libc_start_main
0x00400690    4 50   -> 41   sym.deregister_tm_clones
0x004006d0    4 58   -> 55   sym.register_tm_clones
0x00400710    3 28           sym.__do_global_dtors_aux
0x00400730    4 38   -> 35   entry.init0
0x00400960    1 2            sym.__libc_csu_fini
0x00400964    1 9            sym._fini
0x004008f0    4 101          sym.__libc_csu_init
0x00400756   12 407          main
0x00400590    3 26           sym._init
0x00400630    1 6            loc.imp.__gmon_start__
0x004005c0    1 6            sym.imp.remove
0x004005d0    1 6            sym.imp.fclose
0x004005e0    1 6            sym.imp.strlen
0x004005f0    1 6            sym.imp.__stack_chk_fail
0x00400600    1 6            sym.imp.fputc
0x00400620    1 6            sym.imp.fprintf
0x00400640    1 6            sym.imp.fseek
0x00400650    1 6            sym.imp.fopen

在找到程序内存在的函数后,可以使用axt命令来查看函数调用

代码语言:javascript
复制
[0x00400660]> axt main
entry0 0x40067d [DATA] mov rdi, main

在找到main函数后,使用s命令定位到main函数,pdf命令来查看函数的反汇编代码,s命令后可以加地址或者函数名

代码语言:javascript
复制
[0x00400660]> s main
[0x00400756]> pdf
            ; DATA XREF from entry0 @ 0x40067d
┌ 407: int main (int argc, char **argv, char **envp);
│           ; var int64_t var_40h @ rbp-0x40
│           ; var int64_t var_3ch @ rbp-0x3c
│           ; var file*stream @ rbp-0x38
│           ; var char *filename @ rbp-0x30
│           ; var int64_t var_28h @ rbp-0x28
│           ; var int64_t var_24h @ rbp-0x24
│           ; var int64_t canary @ rbp-0x18
│           0x00400756      55             push rbp
│           0x00400757      4889e5         mov rbp, rsp
│           0x0040075a      53             push rbx
│           0x0040075b      4883ec38       sub rsp, 0x38
│           0x0040075f      64488b042528.  mov rax, qword fs:[0x28]
│           0x00400768      488945e8       mov qword [canary], rax
│           0x0040076c      31c0           xor eax, eax
│           0x0040076e      c745c0000000.  mov dword [var_40h], 0
│           ; CODE XREF from main @ 0x4007c5
│       ┌─> 0x00400775      8b45c0         mov eax, dword [var_40h]
│       ╎   0x00400778      4863d8         movsxd rbx, eax
│       ╎   0x0040077b      bfa0106000     mov edi, obj.s              ; 0x6010a0 ; "c61b68366edeb7bdce3c6820314b7498" ; const char *s
│       ╎   0x00400780      e85bfeffff     call sym.imp.strlen         ; size_t strlen(const char *s)
│       ╎   0x00400785      4839c3         cmp rbx, rax
│      ┌──< 0x00400788      733d           jae 0x4007c7
│      │╎   0x0040078a      8b45c0         mov eax, dword [var_40h]
│      │╎   0x0040078d      8d500a         lea edx, [rax + 0xa]
│      │╎   0x00400790      8b45c0         mov eax, dword [var_40h]
│      │╎   0x00400793      4898           cdqe
│      │╎   0x00400795      0fb680a01060.  movzx eax, byte [rax + obj.s] ; [0x6010a0:1]=99 ; "c61b68366edeb7bdce3c6820314b7498"
│      │╎   0x0040079c      89c1           mov ecx, eax
│      │╎   0x0040079e      8b45c0         mov eax, dword [var_40h]
│      │╎   0x004007a1      83e001         and eax, 1
│      │╎   0x004007a4      85c0           test eax, eax
│     ┌───< 0x004007a6      7407           je 0x4007af
│     ││╎   0x004007a8      b801000000     mov eax, 1
│    ┌────< 0x004007ad      eb05           jmp 0x4007b4
│    │││╎   ; CODE XREF from main @ 0x4007a6
│    │└───> 0x004007af      b8ffffffff     mov eax, 0xffffffff         ; -1
│    │ │╎   ; CODE XREF from main @ 0x4007ad
│    └────> 0x004007b4      01c8           add eax, ecx
│      │╎   0x004007b6      89c1           mov ecx, eax
│      │╎   0x004007b8      4863c2         movsxd rax, edx
│      │╎   0x004007bb      8888e0106000   mov byte [rax + obj.t], cl  ; [0x6010e0:1]=83 ; "SharifCTF{????????????????????????????????}"
│      │╎   0x004007c1      8345c001       add dword [var_40h], 1
│      │└─< 0x004007c5      ebae           jmp 0x400775
│      │    ; CODE XREF from main @ 0x400788
│      └──> 0x004007c7      48b82f746d70.  movabs rax, 0x616c662f706d742f ; '/tmp/fla'
│           0x004007d1      488945d0       mov qword [filename], rax
│           0x004007d5      c745d8672e74.  mov dword [var_28h], 0x78742e67 ; 'g.tx'
│           0x004007dc      66c745dc7400   mov word [var_24h], 0x74    ; 't' ; 116
│           0x004007e2      488d45d0       lea rax, [filename]
│           0x004007e6      be74094000     mov esi, 0x400974           ; const char *mode
│           0x004007eb      4889c7         mov rdi, rax                ; const char *filename
│           0x004007ee      e85dfeffff     call sym.imp.fopen          ; file*fopen(const char *filename, const char *mode)
│           0x004007f3      488945c8       mov qword [stream], rax
│           0x004007f7      488b45c8       mov rax, qword [stream]
│           0x004007fb      ba20116000     mov edx, obj.u              ; 0x601120 ; "*******************************************" ;   ...
│           0x00400800      be76094000     mov esi, 0x400976           ; const char *format
│           0x00400805      4889c7         mov rdi, rax                ; FILE *stream
│           0x00400808      b800000000     mov eax, 0
│           0x0040080d      e80efeffff     call sym.imp.fprintf        ; int fprintf(FILE *stream, const char *format,   ...)
│           0x00400812      c745c4000000.  mov dword [var_3ch], 0
│           ; CODE XREF from main @ 0x4008b0
│       ┌─> 0x00400819      8b45c4         mov eax, dword [var_3ch]
│       ╎   0x0040081c      4863d8         movsxd rbx, eax
│       ╎   0x0040081f      bfe0106000     mov edi, obj.t              ; 0x6010e0 ; "SharifCTF{????????????????????????????????}" ; const char *s
│       ╎   0x00400824      e8b7fdffff     call sym.imp.strlen         ; size_t strlen(const char *s)
│       ╎   0x00400829      4839c3         cmp rbx, rax
│      ┌──< 0x0040082c      0f8383000000   jae 0x4008b5
│      │╎   0x00400832      8b45c4         mov eax, dword [var_3ch]
│      │╎   0x00400835      4898           cdqe
│      │╎   0x00400837      8b0485601160.  mov eax, dword [rax*4 + obj.p] ; [0x601160:4]=30
│      │╎   0x0040083e      4863c8         movsxd rcx, eax
│      │╎   0x00400841      488b45c8       mov rax, qword [stream]
│      │╎   0x00400845      ba00000000     mov edx, 0                  ; int whence
│      │╎   0x0040084a      4889ce         mov rsi, rcx                ; long offset
│      │╎   0x0040084d      4889c7         mov rdi, rax                ; FILE *stream
│      │╎   0x00400850      e8ebfdffff     call sym.imp.fseek          ; int fseek(FILE *stream, long offset, int whence)
│      │╎   0x00400855      8b45c4         mov eax, dword [var_3ch]
│      │╎   0x00400858      4898           cdqe
│      │╎   0x0040085a      8b0485601160.  mov eax, dword [rax*4 + obj.p] ; [0x601160:4]=30
│      │╎   0x00400861      4898           cdqe
│      │╎   0x00400863      0fb680e01060.  movzx eax, byte [rax + obj.t] ; [0x6010e0:1]=83 ; "SharifCTF{????????????????????????????????}"
│      │╎   0x0040086a      0fbec0         movsx eax, al
│      │╎   0x0040086d      488b55c8       mov rdx, qword [stream]
│      │╎   0x00400871      4889d6         mov rsi, rdx                ; FILE *stream
│      │╎   0x00400874      89c7           mov edi, eax                ; int c
│      │╎   0x00400876      e885fdffff     call sym.imp.fputc          ; int fputc(int c, FILE *stream)
│      │╎   0x0040087b      488b45c8       mov rax, qword [stream]
│      │╎   0x0040087f      ba00000000     mov edx, 0                  ; int whence
│      │╎   0x00400884      be00000000     mov esi, 0                  ; long offset
│      │╎   0x00400889      4889c7         mov rdi, rax                ; FILE *stream
│      │╎   0x0040088c      e8affdffff     call sym.imp.fseek          ; int fseek(FILE *stream, long offset, int whence)
│      │╎   0x00400891      488b45c8       mov rax, qword [stream]
│      │╎   0x00400895      ba20116000     mov edx, obj.u              ; 0x601120 ; "*******************************************" ;   ...
│      │╎   0x0040089a      be76094000     mov esi, 0x400976           ; const char *format
│      │╎   0x0040089f      4889c7         mov rdi, rax                ; FILE *stream
│      │╎   0x004008a2      b800000000     mov eax, 0
│      │╎   0x004008a7      e874fdffff     call sym.imp.fprintf        ; int fprintf(FILE *stream, const char *format,   ...)
│      │╎   0x004008ac      8345c401       add dword [var_3ch], 1
│      │└─< 0x004008b0      e964ffffff     jmp 0x400819
│      │    ; CODE XREF from main @ 0x40082c
│      └──> 0x004008b5      488b45c8       mov rax, qword [stream]
│           0x004008b9      4889c7         mov rdi, rax                ; FILE *stream
│           0x004008bc      e80ffdffff     call sym.imp.fclose         ; int fclose(FILE *stream)
│           0x004008c1      488d45d0       lea rax, [filename]
│           0x004008c5      4889c7         mov rdi, rax                ; const char *filename
│           0x004008c8      e8f3fcffff     call sym.imp.remove         ; int remove(const char *filename)
│           0x004008cd      b800000000     mov eax, 0
│           0x004008d2      488b5de8       mov rbx, qword [canary]
│           0x004008d6      6448331c2528.  xor rbx, qword fs:[0x28]
│       ┌─< 0x004008df      7405           je 0x4008e6
│       │   0x004008e1      e80afdffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
│       │   ; CODE XREF from main @ 0x4008df
│       └─> 0x004008e6      4883c438       add rsp, 0x38
│           0x004008ea      5b             pop rbx
│           0x004008eb      5d             pop rbp
└           0x004008ec      c3             ret

如果觉得看反汇编不过瘾也可以通过px命令查看十六进制内容

代码语言:javascript
复制
[0x00400756]> px
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00400756  5548 89e5 5348 83ec 3864 488b 0425 2800  UH..SH..8dH..%(.                                                                                                                     
0x00400766  0000 4889 45e8 31c0 c745 c000 0000 008b  ..H.E.1..E......
0x00400776  45c0 4863 d8bf a010 6000 e85b feff ff48  E.Hc....`..[...H
0x00400786  39c3 733d 8b45 c08d 500a 8b45 c048 980f  9.s=.E..P..E.H..
0x00400796  b680 a010 6000 89c1 8b45 c083 e001 85c0  ....`....E......
0x004007a6  7407 b801 0000 00eb 05b8 ffff ffff 01c8  t...............
0x004007b6  89c1 4863 c288 88e0 1060 0083 45c0 01eb  ..Hc.....`..E...
0x004007c6  ae48 b82f 746d 702f 666c 6148 8945 d0c7  .H./tmp/flaH.E..
0x004007d6  45d8 672e 7478 66c7 45dc 7400 488d 45d0  E.g.txf.E.t.H.E.
0x004007e6  be74 0940 0048 89c7 e85d feff ff48 8945  .t.@.H...]...H.E
0x004007f6  c848 8b45 c8ba 2011 6000 be76 0940 0048  .H.E.. .`..v.@.H
0x00400806  89c7 b800 0000 00e8 0efe ffff c745 c400  .............E..
0x00400816  0000 008b 45c4 4863 d8bf e010 6000 e8b7  ....E.Hc....`...
0x00400826  fdff ff48 39c3 0f83 8300 0000 8b45 c448  ...H9........E.H
0x00400836  988b 0485 6011 6000 4863 c848 8b45 c8ba  ....`.`.Hc.H.E..
0x00400846  0000 0000 4889 ce48 89c7 e8eb fdff ff8b  ....H..H........

同时,为了能够更好的理解程序的功能,iz命令可以查看程序中的字符串

代码语言:javascript
复制
[0x00400756]> iz
[Strings]
nth paddr      vaddr      len size section type  string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x000010a0 0x006010a0 32  33   .data   ascii c61b68366edeb7bdce3c6820314b7498
1   0x000010e0 0x006010e0 43  44   .data   ascii SharifCTF{????????????????????????????????}
2   0x00001120 0x00601120 43  44   .data   ascii *******************************************

字符串和函数一样,可以使用axt命令查看是哪里把它打印出来的

代码语言:javascript
复制
[0x00400756]> axt 0x6010a0
main 0x40077b [DATA] mov edi, obj.s
main 0x400795 [DATA] movzx eax, byte [rax + obj.s]

r2还提供了可视模式,可以更直观的分析函数的调用,vv命令进入

以上是使用r2静态分析二进制文件,然后r2的功能不止于此,它还可以动态调试二进制文件甚至给我函数的伪代码

使用r2 -d -A ./program命令来进入调试器

代码语言:javascript
复制
$ r2 -d -A ./e3dd9674429f4ce1a25c08ea799fc027
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Finding and parsing C++ vtables (avrr)
[x] Skipping type matching analysis in debugger mode (aaft)
[x] Propagate noreturn information (aanr)
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x7f8186b18050]>

动态调试的主要命令

代码语言:javascript
复制
db:断点,db后可以跟函数名或者地址
dbi:查看已有断点
dc:运行程序
dbt:查看堆栈
dr:查看寄存器
代码语言:javascript
复制
$ r2 -d -A ./e3dd9674429f4ce1a25c08ea799fc027 
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Finding and parsing C++ vtables (avrr)
[x] Skipping type matching analysis in debugger mode (aaft)
[x] Propagate noreturn information (aanr)
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x7f53c8464050]> db main
[0x7f53c8464050]> dbi
0 0x00400756 E:1 T:0
[0x7f53c8464050]> dc
hit breakpoint at: 0x400756
[0x00400756]> dbt
0  0x400756           sp: 0x0                 0    [main]  main entry.init0+38
[0x00400756]> dr
rax = 0x00400756
rbx = 0x004008f0
rcx = 0x7f53c8443738
rdx = 0x7ffcee042568
r8 = 0x00000000
r9 = 0x7f53c84731f0
r10 = 0xfffffffffffffb8c
r11 = 0x7f53c829c730
r12 = 0x00400660
r13 = 0x00000000
r14 = 0x00000000
r15 = 0x00000000
rsi = 0x7ffcee042558
rdi = 0x00000001
rsp = 0x7ffcee042468
rbp = 0x00000000
rip = 0x00400756
rflags = 0x00000246
orax = 0xffffffffffffffff

同时,r2可以通过插件实现反编译功能,使用r2pm -l命令查看当前插件,r2的插件有很多,这里使用r2dec反编译插件来实现对程序的反编译,r2pm -install r2dec来安装,安装完成后可以直接在r2中使用-A加载程序,然后使用r2dec反汇编程序,反汇编的命令是pdda

代码语言:javascript
复制
$ r2 -A ./e3dd9674429f4ce1a25c08ea799fc027
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x00400660]> s main
[0x00400756]> pdda
    ; assembly                                           | /* r2dec pseudo code output */
                                                         | /* ./e3dd9674429f4ce1a25c08ea799fc027 @ 0x400756 */
                                                         | #include <stdint.h>
                                                         |  
    ; (fcn) main ()                                      | int32_t main (void) {
                                                         |     int64_t var_40h;
                                                         |     int64_t var_3ch;
                                                         |     file* stream;
                                                         |     char * filename;
                                                         |     int64_t var_28h;
                                                         |     int64_t var_24h;
                                                         |     int64_t canary;
    0x00400756 push rbp                                  |     
    0x00400757 mov rbp, rsp                              |     
    0x0040075a push rbx                                  |     
    0x0040075b sub rsp, 0x38                             |     
    0x0040075f mov rax, qword fs:[0x28]                  |     rax = *(fs:0x28);
    0x00400768 mov qword [rbp - 0x18], rax               |     *((rbp - 0x18)) = rax;
    0x0040076c xor eax, eax                              |     eax = 0;
    0x0040076e mov dword [rbp - 0x40], 0                 |     *((rbp - 0x40)) = 0;
                                                         |     do {
    0x00400775 mov eax, dword [rbp - 0x40]               |         eax = *((rbp - 0x40));
    0x00400778 movsxd rbx, eax                           |         rbx = (int64_t) eax;
    0x0040077b mov edi, 0x6010a0                         |         
    0x00400780 call 0x4005e0                             |         rax = strlen ("c61b68366edeb7bdce3c6820314b7498");
    0x00400785 cmp rbx, rax                              |         
                                                         |         if (rbx >= rax) {
    0x00400788 jae 0x4007c7                              |             goto label_0;
                                                         |         }
    0x0040078a mov eax, dword [rbp - 0x40]               |         eax = *((rbp - 0x40));
    0x0040078d lea edx, [rax + 0xa]                      |         edx = rax + 0xa;
    0x00400790 mov eax, dword [rbp - 0x40]               |         eax = *((rbp - 0x40));
    0x00400793 cdqe                                      |         rax = (int64_t) eax;
    0x00400795 movzx eax, byte [rax + 0x6010a0]          |         eax = *((rax + obj.s));
    0x0040079c mov ecx, eax                              |         ecx = eax;
    0x0040079e mov eax, dword [rbp - 0x40]               |         eax = *((rbp - 0x40));
    0x004007a1 and eax, 1                                |         eax &= 1;
    0x004007a4 test eax, eax                             |         
                                                         |         if (eax != 0) {
    0x004007a6 je 0x4007af                               |             
    0x004007a8 mov eax, 1                                |             eax = 1;
    0x004007ad jmp 0x4007b4                              |             
                                                         |         } else {
    0x004007af mov eax, 0xffffffff                       |             eax = 0xffffffff;
                                                         |         }
    0x004007b4 add eax, ecx                              |         eax += ecx;
    0x004007b6 mov ecx, eax                              |         ecx = eax;
    0x004007b8 movsxd rax, edx                           |         rax = (int64_t) edx;
    0x004007bb mov byte [rax + 0x6010e0], cl             |         *((rax + obj.t)) = cl;
    0x004007c1 add dword [rbp - 0x40], 1                 |         *((rbp - 0x40))++;
    0x004007c5 jmp 0x400775                              |         
                                                         |     } while (1);
                                                         | label_0:
    0x004007c7 movabs rax, 0x616c662f706d742f            |     rax = 0x616c662f706d742f;
    0x004007d1 mov qword [rbp - 0x30], rax               |     *((rbp - 0x30)) = rax;
    0x004007d5 mov dword [rbp - 0x28], 0x78742e67        |     *((rbp - 0x28)) = 0x78742e67;
    0x004007dc mov word [rbp - 0x24], 0x74               |     *((rbp - 0x24)) = 0x74;
    0x004007e2 lea rax, [rbp - 0x30]                     |     rax = rbp - 0x30;
    0x004007e6 mov esi, 0x400974                         |     
    0x004007eb mov rdi, rax                              |     
    0x004007ee call 0x400650                             |     rax = fopen (rax, 0x400974);
    0x004007f3 mov qword [rbp - 0x38], rax               |     *((rbp - 0x38)) = rax;
    0x004007f7 mov rax, qword [rbp - 0x38]               |     rax = *((rbp - 0x38));
    0x004007fb mov edx, 0x601120                         |     edx = "*******************************************";
    0x00400800 mov esi, 0x400976                         |     
    0x00400805 mov rdi, rax                              |     
    0x00400808 mov eax, 0                                |     eax = 0;
    0x0040080d call 0x400620                             |     fprintf (rax, 0x400976);
    0x00400812 mov dword [rbp - 0x3c], 0                 |     *((rbp - 0x3c)) = 0;
                                                         |     do {
    0x00400819 mov eax, dword [rbp - 0x3c]               |         eax = *((rbp - 0x3c));
    0x0040081c movsxd rbx, eax                           |         rbx = (int64_t) eax;
    0x0040081f mov edi, 0x6010e0                         |         
    0x00400824 call 0x4005e0                             |         rax = strlen ("SharifCTF{????????????????????????????????}");
    0x00400829 cmp rbx, rax                              |         
                                                         |         if (rbx >= rax) {
    0x0040082c jae 0x4008b5                              |             goto label_1;
                                                         |         }
    0x00400832 mov eax, dword [rbp - 0x3c]               |         eax = *((rbp - 0x3c));
    0x00400835 cdqe                                      |         rax = (int64_t) eax;
    0x00400837 mov eax, dword [rax*4 + 0x601160]         |         eax = *((rax*4 + obj.p));
    0x0040083e movsxd rcx, eax                           |         rcx = (int64_t) eax;
    0x00400841 mov rax, qword [rbp - 0x38]               |         rax = *((rbp - 0x38));
    0x00400845 mov edx, 0                                |         
    0x0040084a mov rsi, rcx                              |         
    0x0040084d mov rdi, rax                              |         
    0x00400850 call 0x400640                             |         fseek (rax, rcx, 0);
    0x00400855 mov eax, dword [rbp - 0x3c]               |         eax = *((rbp - 0x3c));
    0x00400858 cdqe                                      |         rax = (int64_t) eax;
    0x0040085a mov eax, dword [rax*4 + 0x601160]         |         eax = *((rax*4 + obj.p));
    0x00400861 cdqe                                      |         rax = (int64_t) eax;
    0x00400863 movzx eax, byte [rax + 0x6010e0]          |         eax = *((rax + obj.t));
    0x0040086a movsx eax, al                             |         eax = (int32_t) al;
    0x0040086d mov rdx, qword [rbp - 0x38]               |         rdx = *((rbp - 0x38));
    0x00400871 mov rsi, rdx                              |         
    0x00400874 mov edi, eax                              |         
    0x00400876 call 0x400600                             |         fputc (eax, *((rbp - 0x38)));
    0x0040087b mov rax, qword [rbp - 0x38]               |         rax = *((rbp - 0x38));
    0x0040087f mov edx, 0                                |         edx = 0;
    0x00400884 mov esi, 0                                |         
    0x00400889 mov rdi, rax                              |         
    0x0040088c call 0x400640                             |         fseek (rax, 0, edx);
    0x00400891 mov rax, qword [rbp - 0x38]               |         rax = *((rbp - 0x38));
    0x00400895 mov edx, 0x601120                         |         edx = "*******************************************";
    0x0040089a mov esi, 0x400976                         |         
    0x0040089f mov rdi, rax                              |         
    0x004008a2 mov eax, 0                                |         eax = 0;
    0x004008a7 call 0x400620                             |         fprintf (rax, 0x400976);
    0x004008ac add dword [rbp - 0x3c], 1                 |         *((rbp - 0x3c))++;
    0x004008b0 jmp 0x400819                              |         
                                                         |     } while (1);
                                                         | label_1:
    0x004008b5 mov rax, qword [rbp - 0x38]               |     rax = *((rbp - 0x38));
    0x004008b9 mov rdi, rax                              |     
    0x004008bc call 0x4005d0                             |     fclose (*((rbp - 0x38)));
    0x004008c1 lea rax, [rbp - 0x30]                     |     rax = rbp - 0x30;
    0x004008c5 mov rdi, rax                              |     
    0x004008c8 call 0x4005c0                             |     remove (rax);
    0x004008cd mov eax, 0                                |     eax = 0;
    0x004008d2 mov rbx, qword [rbp - 0x18]               |     rbx = *((rbp - 0x18));
    0x004008d6 xor rbx, qword fs:[0x28]                  |     rbx ^= *(fs:0x28);
                                                         |     if (*((rbp - 0x3c)) != 0) {
    0x004008df je 0x4008e6                               |         
    0x004008e1 call 0x4005f0                             |         stack_chk_fail ();
                                                         |     }
    0x004008e6 add rsp, 0x38                             |     
    0x004008ea pop rbx                                   |     
    0x004008eb pop rbp                                   |     
    0x004008ec ret                                       |     return rax;
                                                         | }

这样可以清晰的对比观察汇编代码和反编译后的伪代码,更方便观察。

radare2还有很多插件可以使用,大家有兴趣的话可以在深入研究一下。

0x04 题目实例

getit这是攻防世界的一道re题,这道题拿到手是个elf文件,我首先是放到ida里看了看伪代码

代码语言:javascript
复制
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // al
  int i; // [rsp+0h] [rbp-40h]
  int j; // [rsp+4h] [rbp-3Ch]
  FILE *stream; // [rsp+8h] [rbp-38h]
  char filename[24]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v9; // [rsp+28h] [rbp-18h]

  v9 = __readfsqword(0x28u);
  for ( i = 0; i < strlen(s); ++i )
  {
    if ( (i & 1) != 0 )
      v3 = 1;
    else
      v3 = -1;
    *(&t + i + 10) = s[i] + v3;
  }
  strcpy(filename, "/tmp/flag.txt");
  stream = fopen(filename, "w");
  fprintf(stream, "%s\n", u);
  for ( j = 0; j < strlen(&t); ++j )
  {
    fseek(stream, p[j], 0);
    fputc(*(&t + p[j]), stream);
    fseek(stream, 0LL, 0);
    fprintf(stream, "%s\n", u);
  }
  fclose(stream);
  remove(filename);
  return 0;
}

本来这道题目应该是写逆向算法得到flag,但是经过分析和与反汇编代码对比,发现flag应该是被存在了eax里面

在调试程序的时候,我们可以ida配合gdb来说使用,虽然ida本身也有动态调试的功能,但是我推荐用ida来分析反汇编和伪代码,然后通过gdb或者r2来进行动态调试查看寄存器的值,或者使用r2反编译和反汇编代码对比分析,这样就可以方便不少,这里猜测flag应该存在eax中,可以通过gdb动态调试程序,在0x400832处下断点,让程序运行

运行程序到断点处,查看寄存器存储的地址的值,就能得到flag

这样通过动态调试的方式,省了很多事。

0x05 总结

本文简单介绍了ida、gdb和r2动态调试二进制文件的方法,也是自己最近在做ctf题目的时候使用的,之前只会用od和ida,使用gdb和r2很少,正好借此机会也学习了一下,对于我这种菜鸡来说,在分析二进制文件的时候,3种工具一起使用效果会好一些。

代码语言:javascript
复制
参考文章:
https://wizardforcel.gitbooks.io/100-gdb-tips/content/print-registers.html
https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html
https://linux.cn/article-13074-1.html
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿鹄实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态调试elf文件的几种方法
    • 0x01 ida动态调试
      • 0x02 gdb动态调试
        • 0x03 radare2动态调试
          • 0x04 题目实例
            • 0x05 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档