313游戏网 手游攻略 手游评测 Linux CTF 逆向工程入门

Linux CTF 逆向工程入门

时间:2024-08-28 18:27:43 来源:网络 浏览:0

各位老铁们,大家好,今天由我来为大家分享Linux CTF 逆向工程入门,以及的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!

ELF更详细的描述: e_shoff:节头表的文件偏移量(字节)。如果文件没有节头表,则该成员的值为零。 sh_offset:表示该节距文件头的距离

+--------------------+ | ELF 标头|---++--------- +------------ ----------+ | e_shoff| | |--+|部分|节标题0 || | |---+ sh_offset|标头+------------- -----+ || |节标题1 |---|--+ sh_offset|表+-------------------+ | || |节标题2 |---|--|--++--------- +--------------------+ | | | |第0 节| --+ | | +--------------------+ | | sh_偏移量|第1 节|-----+ | +--------- ----------+ | |第2 节|--------+ +--------------------+

#2.可执行头部(Executable Header)

ELF 文件的第一部分是可执行文件头,其中包含有关ELF 文件类型的信息。 ELF文件在各种平台上通用。 ELF 文件有32 位和64 位版本。文件头内容相同,但部分成员的大小不同。它的文件图也有两个版本:称为“Elf32_Ehdr”和“Elf64_Ehdr”。以下以32 位版本为例:

#define EI_NIDENT (16) typedef struct { unsigned char e_ident[EI_NIDENT]; /* 幻数和其他信息*/Elf32_Half e_type; /* 目标文件类型*/Elf32_Half e_machine; /* 架构*/Elf32_Word e_version; /* 目标文件版本*/Elf32_Addr e_entry; /* 。。点虚拟地址*/Elf32_Off e_phoff; /* 程序头表文件偏移*/Elf32_Off e_shoff; /* 节头表文件偏移*/Elf32_Word e_flags; /* 处理器特定标志*/Elf32_Half e_ehsize; /* ELF 标头大小(以字节为单位)*/Elf32_Half e_phentsize; /* 程序头表项大小*/Elf32_Half e_phnum; /* 程序头表项计数*/Elf32_Half e_shentsize; /* 节头表项大小*/Elf32_Half e_shnum; /* 节头表项计数*/Elf32_Half e_shstrndx; /* 节头字符串表索引*/} Elf32_Ehdr;使用readelf分析ELF文件格式

# readelf -h /bin/lsELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2 的补码,小尾数Version: 1(当前)OS/ABI: UNIX - 系统V ABI 版本: 0 类型: DYN (共享目标文件) 机器: Advanced Micro Devices 程序头: 56 (字节) 程序头数量: 11 节头大小: 64 (字节) 节头数量: 29 节头字符串表索引: 28我们可以使用下面的计算方法来计算整个二进制文件的大小:

大小=e_shoff + (e_shnum * e_shentsize)

大小=节标题的开始+(节标题的数量* 节标题的大小)

size=137000 + (29*64)=138856 计算结果验证:

# ls -l /bin/ls-rwxr-xr-x 1 root root 138856 Aug 29 21:20 /bin/ls

#3、程序头部(Program Headers)

程序头是文件中各个段的描述,用于告诉系统如何创建过程图像。

typedef 结构{ Elf32_Word p_type; /* 段类型*/Elf32_Off p_offset; /* 段文件偏移量*/Elf32_Addr p_vaddr; /* 段虚拟地址*/Elf32_Addr p_paddr; /* 段物理地址*/Elf32_Word p_filesz; /* 文件中的段大小*/Elf32_Word p_memsz; /* 内存中的段大小*/Elf32_Word p_flags; /* 段标志*/Elf32_Word p_align; /* 段对齐*/} Elf32_Phdr;

#4、节表头部(Section Headers)

节头包含描述文件的节信息,例如大小、偏移量等,但这些对于二进制文件的执行流程并不重要。

段或段:段从运行的角度描述elf文件,段从链接的角度描述elf文件。也就是说,在链接阶段,我们可以忽略程序头表来处理这个文件,而在运行阶段,我们可以忽略它。节头表来处理这个程序(所以很多加固方法删除了节头表)。从图中我们还可以看出,段和段是包含的,一个段又包含多个段。

typedef struct { Elf32_Word sh_name; /* 节名(字符串表索引) */Elf32_Word sh_type; /*节类别*/Elf32_Word sh_flags; /* 进程中段执行的特征(读、写) */Elf32_Addr sh_addr; /* 内存中起始虚拟地址*/Elf32_Off sh_offset; /* 该节在文件中的偏移量*/Elf32_Word sh_size; /* 节大小(以字节为单位) */Elf32_Word sh_link; /* 链接到另一个部分*/Elf32_Word sh_info; /* 附加节信息*/Elf32_Word sh_addralign; /* 节对齐*/Elf32_Word sh_entsize; /* 如果节保存表的话条目大小*/} Elf32_Shdr;

#5、表(Section)

Linux CTF 逆向工程入门

#5.1 .bss Section

保存未初始化的数据,例如那些未初始化的全局变量。

#5.2 .data Section

保存初始化数据。

#5.3 .rodata Section

在程序中保存只读数据。

#5.4 .text Section

本节包含程序的实际代码和逻辑流程。使用readelf查看ELF文件表结构

# readelf -S --wide /bin/ls 有29 个节头,从偏移量0x21728:Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] 。 interp PROGBITS 00000000000002a8 0002a8 00001c 00 A 0 0 1 [ 2] .note.ABI-tag 注00000000000002c4 0002c4 000020 00 A 0 4 [ 3] .note.gnu.build-id 注00000000 000002e4 0002e4 000024 00 A 0 0 4 [4 ] .gnu.hash GNU_HASH 0000000000000308 000308 0000c0 00 A 5 0 8 [ 5] .dynsym DYNSYM 00000000000003c8 0003c8 000c90 18 A 6 1 8 [ 6] .dynstr STRTAB 00 00000000001058 001058 0005d8 00 A 0 0 1 [7] .gnu.版本VERSYM 0000000000001630 001630 00010c 02 A 5 0 2 [ 8 ] .gnu.version_r VERNEED 0000000000001740 001740 000070 00 A 6 1 8 [ 9 ] .rela.dyn RELA 00000 000000017b0 0017b0 0013 50 18 A 5 0 8 [10] .rela.plt RELA 0000000000002b00 002b00 0009f0 18 AI 5 24 8 [11] .init PROGBITS 0000000000004000 004000 000017 00 AX 0 0 4 [12] .plt PROGBITS 000000000000402 0 004020 0006b0 10 AX 0 0 16 [13] .plt.got PROGBITS 00000000000046d0 0046d0 000018 08 AX 0 0 8 [ 14] .text PROGBITS 00000000000046f0 0046f0 01253e 00 AX 0 0 16 [15] .fini PROGBITS 0000000000016c30 016c30 000009 00 AX 0 0 4 [16] .rodata PROGB ITS 00 00000000017000 017000 005129 00 A 0 0 32 [17] .eh_frame_hdr程序000000000001c12c 01c12c 0008fc 00 A 0 0 4 [18] .eh_frame 程序000000000001ca28 01ca28 002ed0 00 A 0 0 8 [19] .init_array INIT_ARRAY 00000000000 21390 020390 000008 08 WA 0 0 8 [20] .fini_array FINI_ARRAY 0000000000021398 020398 000008 08 WA 0 0 8 [21] .data.rel.ro PROGBITS 00000000000213a0 0203a0 000a38 00 WA 0 0 32 [22] .dynamic DYNAMIC 0000000000021dd8 020dd8 0001f0 10 WA 6 0 8 [23] .got PROGBITS 00000000 00021fc8 020fc8 000038 08 西澳0 0 8 [24 ] .got.plt PROGBITS 0000000000022000 021000 000368 08 WA 0 0 8 [25] .data PROGBITS 0000000000022380 021380 000268 00 WA 0 0 32 [26] .bss NOBITS 00 0000000002 2600 0215e8 0012d8 00 WA 0 0 32 [27] .gnu_debuglink PROGBITS 0000000000000000 0215e8 000034 00 0 0 4 [28] .shstrtab STRTAB 0000000000000000 02161c 00010a 00 0 0 1Flags: 的关键字W(写入)、A(分配)、X(执行)、M(合并)、S(字符串)、I(信息) 、L(链接顺序)、O(需要额外的操作系统处理)、G(组)、T(TLS)、C(压缩)、x(未知)、o(特定于操作系统)、E(排除)、l(大) , p(特定于处理器)

#6、完成简单的CTF挑战

现在您已经了解了有关ELF 文件的一些知识,让我们找一个CTF 问题来尝试一下。

二进制文件下载地址:https://ufile.io/blvpm

国内下载:https://www.lanzous.com/i34qg6f

1. 运行该程序并向其传递一些随机字符。结果如下:

# ./nix_5744af788e6cbdb29bb41e8b0e5f3cd5 aaaa[+] 没有适合你的标志。 [+] 2.然后用strings检查程序的字符串,看看是否能找到有用的信息

Linux CTF 逆向工程入门

# 字符串nix_5744af788e6cbdb29bb41e8b0e5f3cd5 /lib/ld-linux.so.2Mw1i#'0libc.so.6_IO_stdin_usedexitsprintfputsstrlen__cxa_finalize__libc_start_mainGLIBC_2.1.3Y[^][^_]UWVS[^_]Usage: script.ex keyLength argv[1] 太长。[ + ] 标志是: SAYCURE{%s} [+][+] 没有适合您的标志。 [+]%c%c%c%c%c%c%c%c%c%c%c%c%c% c%c;*2#34;GCC: (Debian 8.2.0-8) 8.2。 0crtstuff.c 可以看到“%c”是打印flag的字符串,数字是15。

3.我们可以查看“.rodata”部分的偏移量,以便更好地查看这些字符。

# readelf -x .rodata nix_5744af788e6cbdb29bb41e8b0e5f3cd5节'.rodata':0x00002000 03000000 01000200 55736167 653a2073 .Usage: s0x0 00 02010 63726970 742e6578 65203c6b 65793e00 cript.exe 密钥。0x00002020 4c656e67 7468206f 66206172 67765b31 argv 的长度[10x00002030 5d20746f 6f206c6f 6e672e00 5b2b5d20]太长.[+]0x00002040 54686520 666c6167 2069733a 20534159 标志为: SAY0x00002050 43555245 7b25737d 205b2b5d 0a000a5b CURE{%s} [+].[0x00002060 2b5d204e 6f20666c 61672066 6f722079 +] y 没有标志0x00002070 6f752e20 5b2b5d00 25632563 25632563 ou。 [+].%c%c%c%c0x00002080 25632563 25632563 25632563 %c%c%c%c%c% c%c0x00002090 25632563 256300 %c%c%c。 4. 检查符号表(Symbols)。使用nm命令查看库文件的符号。

# nm -D nix_5744af788e6cbdb29bb41e8b0e5f3cd5 w __cxa_finalize U exit w __gmon_start__00002004 R _IO_stdin_used w _ITM_registerTMCloneTable w _ITM_registerTMCloneTable U __libc_start_main U printf U put U sprintf U strlen 描述:动态:

显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义 我们可以发现 printf, puts, sprintf, strlen functions.这些函数未定义。 5、跟踪系统调用(System Calls) 我们可以使用strace之类的工具去跟踪程序的系统调用 # strace ./nix_5744af788e6cbdb29bb41e8b0e5f3cd5 aaaaexecve("./nix_5744af788e6cbdb29bb41e8b0e5f3cd5", ["./nix_5744af788e6cbdb29bb41e8b0e"..., "aaaa"], 0x7ffd5ff92d18 /* 46 vars */) = 0strace: [ Process PID=59965 runs in 32 bit mode. ]brk(NULL) = 0x56f14000access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7ef0000access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3fstat64(3, {st_mode=S_IFREG|0644, st_size=220471, ...}) = 0mmap2(NULL, 220471, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7eba000close(3) = 0access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)openat(AT_FDCWD, "/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0 \233\1\0004\0\0\0"..., 512) = 512fstat64(3, {st_mode=S_IFREG|0755, st_size=1930924, ...}) = 0mmap2(NULL, 1940000, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xf7ce0000mprotect(0xf7cf9000, 1814528, PROT_NONE) = 0mmap2(0xf7cf9000, 1359872, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19000) = 0xf7cf9000mmap2(0xf7e45000, 450560, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x165000) = 0xf7e45000mmap2(0xf7eb4000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1d3000) = 0xf7eb4000mmap2(0xf7eb7000, 10784, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xf7eb7000close(3) = 0set_thread_area({entry_number=-1, base_addr=0xf7ef10c0, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}) = 0 (entry_number=12)mprotect(0xf7eb4000, 8192, PROT_READ) = 0mprotect(0x5664d000, 4096, PROT_READ) = 0mprotect(0xf7f1e000, 4096, PROT_READ) = 0munmap(0xf7eba000, 220471) = 0fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}) = 0brk(NULL) = 0x56f14000brk(0x56f35000) = 0x56f35000brk(0x56f36000) = 0x56f36000write(1, "\n", 1) = 1write(1, "[+] No flag for you. [+]\n", 25[+] No flag for you. [+]) = 25exit_group(26) = ?+++ exited with 26 +++为了更好地理解,我们可以使用ltrace解码C++来跟踪函数名所做的库调用。 我们可以看到正在进行字符串长度检查。 # ltrace -i -C ./nix_5744af788e6cbdb29bb41e8b0e5f3cd5 aaaaaaaa[0x565570e1] __libc_start_main(0x565571e9, 2, 0xffe3a584, 0x56557400 <unfinished ...>[0x56557249] strlen("aaaaaaaa") = 8[0x565572ca] puts("\n[+] No flag for you. [+]"[+] No flag for you. [+]) = 26[0xffffffffffffffff] +++ exited (status 26) +++6、反编译 ".text"部分 让我们看一下.text部分的反汇编并尝试理解 # objdump -D -M intel -j .text nix_5744af788e6cbdb29bb41e8b0e5f3cd5 nix_5744af788e6cbdb29bb41e8b0e5f3cd5: file format elf32-i386Disassembly of section .text:000010b0 <_start>: 10b0:31 ed xor ebp,ebp 10b2:5e pop esi 10b3:89 e1 mov ecx,esp 10b5:83 e4 f0 and esp,0xfffffff0 10b8:50 push eax 10b9:54 push esp 10ba:52 push edx 10bb:e8 22 00 00 00 call 10e2 <_start+0x32> 10c0:81 c3 40 2f 00 00 add ebx,0x2f40 10c6:8d 83 60 d4 ff ff lea eax,[ebx-0x2ba0] 10cc:50 push eax 10cd:8d 83 00 d4 ff ff lea eax,[ebx-0x2c00] 10d3:50 push eax 10d4:51 push ecx 10d5:56 push esi 10d6:ff b3 f8 ff ff ff push DWORD PTR [ebx-0x8] 10dc:e8 9f ff ff ff call 1080 <__libc_start_main@plt> 10e1:f4 hlt 10e2:8b 1c 24 mov ebx,DWORD PTR [esp] 10e5:c3 ret 10e6:66 90 xchg ax,ax 10e8:66 90 xchg ax,ax 10ea:66 90 xchg ax,ax 10ec:66 90 xchg ax,ax 10ee:66 90 xchg ax,ax... Output Omitted ...000011e9 <main>: 11e9:8d 4c 24 04 lea ecx,[esp+0x4] 11ed:83 e4 f0 and esp,0xfffffff0 11f0:ff 71 fc push DWORD PTR [ecx-0x4] 11f3:55 push ebp 11f4:89 e5 mov ebp,esp 11f6:56 push esi 11f7:53 push ebx 11f8:51 push ecx 11f9:83 ec 1c sub esp,0x1c 11fc:e8 ef fe ff ff call 10f0 <__x86.get_pc_thunk.bx> 1201:81 c3 ff 2d 00 00 add ebx,0x2dff 1207:89 ce mov esi,ecx 1209:c7 45 e4 00 00 00 00 mov DWORD PTR [ebp-0x1c],0x0 1210:c7 45 dc 07 00 00 00 mov DWORD PTR [ebp-0x24],0x7 1217:83 3e 02 cmp DWORD PTR [esi],0x2 121a:74 1c je 1238 <main+0x4f> 121c:83 ec 0c sub esp,0xc 121f:8d 83 08 e0 ff ff lea eax,[ebx-0x1ff8] 1225:50 push eax 1226:e8 15 fe ff ff call 1040 <printf@plt> 122b:83 c4 10 add esp,0x10 122e:83 ec 0c sub esp,0xc 1231:6a 01 push 0x1 1233:e8 28 fe ff ff call 1060 <exit@plt> 1238:8b 46 04 mov eax,DWORD PTR [esi+0x4] 123b:83 c0 04 add eax,0x4 123e:8b 00 mov eax,DWORD PTR [eax] 1240:83 ec 0c sub esp,0xc 1243:50 push eax 1244:e8 27 fe ff ff call 1070 <strlen@plt> 1249:83 c4 10 add esp,0x10 124c:83 f8 0f cmp eax,0xf 124f:76 1c jbe 126d <main+0x84> 1251:83 ec 0c sub esp,0xc 1254:8d 83 20 e0 ff ff lea eax,[ebx-0x1fe0] 125a:50 push eax 125b:e8 f0 fd ff ff call 1050 <puts@plt> 1260:83 c4 10 add esp,0x10 1263:83 ec 0c sub esp,0xc 1266:6a 01 push 0x1 1268:e8 f3 fd ff ff call 1060 <exit@plt> 126d:c7 45 e0 00 00 00 00 mov DWORD PTR [ebp-0x20],0x0 1274:eb 1a jmp 1290 <main+0xa7> 1276:8b 46 04 mov eax,DWORD PTR [esi+0x4] 1279:83 c0 04 add eax,0x4 127c:8b 10 mov edx,DWORD PTR [eax] 127e:8b 45 e0 mov eax,DWORD PTR [ebp-0x20] 1281:01 d0 add eax,edx 1283:0f b6 00 movzx eax,BYTE PTR [eax] 1286:0f be c0 movsx eax,al 1289:01 45 e4 add DWORD PTR [ebp-0x1c],eax 128c:83 45 e0 01 add DWORD PTR [ebp-0x20],0x1 1290:8b 45 e0 mov eax,DWORD PTR [ebp-0x20] 1293:3b 45 dc cmp eax,DWORD PTR [ebp-0x24] 1296:7c de jl 1276 <main+0x8d> 1298:81 7d e4 21 03 00 00 cmp DWORD PTR [ebp-0x1c],0x321 129f:75 1a jne 12bb <main+0xd2> 12a1:e8 33 00 00 00 call 12d9 <comp_key> 12a6:83 ec 08 sub esp,0x8 12a9:50 push eax 12aa:8d 83 3c e0 ff ff lea eax,[ebx-0x1fc4] 12b0:50 push eax 12b1:e8 8a fd ff ff call 1040 <printf@plt> 12b6:83 c4 10 add esp,0x10 12b9:eb 12 jmp 12cd <main+0xe4> 12bb:83 ec 0c sub esp,0xc 12be:8d 83 5e e0 ff ff lea eax,[ebx-0x1fa2] 12c4:50 push eax 12c5:e8 86 fd ff ff call 1050 <puts@plt> 12ca:83 c4 10 add esp,0x10 12cd:90 nop 12ce:8d 65 f4 lea esp,[ebp-0xc] 12d1:59 pop ecx 12d2:5b pop ebx 12d3:5e pop esi 12d4:5d pop ebp 12d5:8d 61 fc lea esp,[ecx-0x4] 12d8:c3 ret 000012d9 <comp_key>: 12d9:55 push ebp 12da:89 e5 mov ebp,esp 12dc:57 push edi 12dd:56 push esi 12de:53 push ebx 12df:83 ec 7c sub esp,0x7c 12e2:e8 09 fe ff ff call 10f0 <__x86.get_pc_thunk.bx> 12e7:81 c3 19 2d 00 00 add ebx,0x2d19 12ed:c7 45 e4 00 00 00 00 mov DWORD PTR [ebp-0x1c],0x0 12f4:c7 45 a8 4c 00 00 00 mov DWORD PTR [ebp-0x58],0x4c 12fb:c7 45 ac 33 00 00 00 mov DWORD PTR [ebp-0x54],0x33 1302:c7 45 b0 74 00 00 00 mov DWORD PTR [ebp-0x50],0x74 1309:c7 45 b4 73 00 00 00 mov DWORD PTR [ebp-0x4c],0x73 1310:c7 45 b8 5f 00 00 00 mov DWORD PTR [ebp-0x48],0x5f 1317:c7 45 bc 67 00 00 00 mov DWORD PTR [ebp-0x44],0x67 131e:c7 45 c0 33 00 00 00 mov DWORD PTR [ebp-0x40],0x33 1325:c7 45 c4 74 00 00 00 mov DWORD PTR [ebp-0x3c],0x74 132c:c7 45 c8 5f 00 00 00 mov DWORD PTR [ebp-0x38],0x5f 1333:c7 45 cc 69 00 00 00 mov DWORD PTR [ebp-0x34],0x69 133a:c7 45 d0 6e 00 00 00 mov DWORD PTR [ebp-0x30],0x6e 1341:c7 45 d4 32 00 00 00 mov DWORD PTR [ebp-0x2c],0x32 1348:c7 45 d8 5f 00 00 00 mov DWORD PTR [ebp-0x28],0x5f 134f:c7 45 dc 52 00 00 00 mov DWORD PTR [ebp-0x24],0x52 1356:c7 45 e0 33 00 00 00 mov DWORD PTR [ebp-0x20],0x33 135d:8b 55 e0 mov edx,DWORD PTR [ebp-0x20] 1360:8b 75 dc mov esi,DWORD PTR [ebp-0x24] 1363:8b 45 d8 mov eax,DWORD PTR [ebp-0x28] 1366:89 45 a4 mov DWORD PTR [ebp-0x5c],eax 1369:8b 4d d4 mov ecx,DWORD PTR [ebp-0x2c] 136c:89 4d a0 mov DWORD PTR [ebp-0x60],ecx 136f:8b 7d d0 mov edi,DWORD PTR [ebp-0x30] 1372:89 7d 9c mov DWORD PTR [ebp-0x64],edi 1375:8b 45 cc mov eax,DWORD PTR [ebp-0x34] 1378:89 45 98 mov DWORD PTR [ebp-0x68],eax 137b:8b 4d c8 mov ecx,DWORD PTR [ebp-0x38] 137e:89 4d 94 mov DWORD PTR [ebp-0x6c],ecx 1381:8b 7d c4 mov edi,DWORD PTR [ebp-0x3c] 1384:89 7d 90 mov DWORD PTR [ebp-0x70],edi 1387:8b 45 c0 mov eax,DWORD PTR [ebp-0x40] 138a:89 45 8c mov DWORD PTR [ebp-0x74],eax 138d:8b 4d bc mov ecx,DWORD PTR [ebp-0x44] 1390:89 4d 88 mov DWORD PTR [ebp-0x78],ecx 1393:8b 7d b8 mov edi,DWORD PTR [ebp-0x48] 1396:89 7d 84 mov DWORD PTR [ebp-0x7c],edi 1399:8b 45 b4 mov eax,DWORD PTR [ebp-0x4c] 139c:89 45 80 mov DWORD PTR [ebp-0x80],eax 139f:8b 7d b0 mov edi,DWORD PTR [ebp-0x50] 13a2:8b 4d ac mov ecx,DWORD PTR [ebp-0x54] 13a5:8b 45 a8 mov eax,DWORD PTR [ebp-0x58] 13a8:83 ec 0c sub esp,0xc 13ab:52 push edx 13ac:56 push esi 13ad:ff 75 a4 push DWORD PTR [ebp-0x5c] 13b0:ff 75 a0 push DWORD PTR [ebp-0x60] 13b3:ff 75 9c push DWORD PTR [ebp-0x64] 13b6:ff 75 98 push DWORD PTR [ebp-0x68] 13b9:ff 75 94 push DWORD PTR [ebp-0x6c] 13bc:ff 75 90 push DWORD PTR [ebp-0x70] 13bf:ff 75 8c push DWORD PTR [ebp-0x74] 13c2:ff 75 88 push DWORD PTR [ebp-0x78] 13c5:ff 75 84 push DWORD PTR [ebp-0x7c] 13c8:ff 75 80 push DWORD PTR [ebp-0x80] 13cb:57 push edi 13cc:51 push ecx 13cd:50 push eax 13ce:8d 83 78 e0 ff ff lea eax,[ebx-0x1f88] 13d4:50 push eax 13d5:8d 83 30 00 00 00 lea eax,[ebx+0x30] 13db:50 push eax 13dc:e8 af fc ff ff call 1090 <sprintf@plt> 13e1:83 c4 50 add esp,0x50 13e4:8d 83 30 00 00 00 lea eax,[ebx+0x30] 13ea:8d 65 f4 lea esp,[ebp-0xc] 13ed:5b pop ebx 13ee:5e pop esi 13ef:5f pop edi 13f0:5d pop ebp 13f1:c3 ret 13f2:66 90 xchg ax,ax 13f4:66 90 xchg ax,ax 13f6:66 90 xchg ax,ax 13f8:66 90 xchg ax,ax 13fa:66 90 xchg ax,ax 13fc:66 90 xchg ax,ax 13fe:66 90 xchg ax,ax... Output Omitted ...在这个二进制文件中,符号没有被剥离,因此我们可以看到函数名称,这使得它更容易理解。 如果你可以阅读汇编代码,你可以很清楚的知道发生了什么。 如果不能阅读汇编代码,让我们做一些实时调试,并尝试更好地理解。 7、实时调试 这里我们使用GDB-Peda进行实时调试 我们首先检查二进制文件中的函数。我们可以看到main,comp_key等函数 gdb-peda$ info functions All defined functions:Non-debugging symbols:0x00001000 _init0x00001040 printf@plt0x00001050 puts@plt0x00001060 exit@plt0x00001070 strlen@plt0x00001080 __libc_start_main@plt0x00001090 sprintf@plt0x000010a0 __cxa_finalize@plt0x000010a8 __gmon_start__@plt0x000010b0 _start0x000010f0 __x86.get_pc_thunk.bx0x00001100 deregister_tm_clones0x00001140 register_tm_clones0x00001190 __do_global_dtors_aux0x000011e0 frame_dummy0x000011e5 __x86.get_pc_thunk.dx0x000011e9 main0x000012d9 comp_key0x00001400 __libc_csu_init0x00001460 __libc_csu_fini0x00001464 _fini调试方法:首先使用 break main 跳到主函数,使用n来step和ni来执行每条指令

Linux CTF 逆向工程入门

gdb-peda$ break mainBreakpoint 1 at 0x11f9gdb-peda$ run aaaaaaaaStarting program: /mnt/hgfs/shared/Linux RE/nix_5744af788e6cbdb29bb41e8b0e5f3cd5 aaaaaaaa[----------------------------------registers-----------------------------------]EAX: 0xf7f95dd8 --> 0xffffd2f0 --> 0xffffd4d1 ("NVM_DIR=/root/.nvm")EBX: 0x0 ECX: 0xffffd250 --> 0x2 EDX: 0xffffd274 --> 0x0 ESI: 0xf7f94000 --> 0x1d5d8c EDI: 0x0 EBP: 0xffffd238 --> 0x0 ESP: 0xffffd22c --> 0xffffd250 --> 0x2 EIP: 0x565561f9 (<main+16>:sub esp,0x1c)EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------] 0x565561f6 <main+13>:push esi 0x565561f7 <main+14>:push ebx 0x565561f8 <main+15>:push ecx=> 0x565561f9 <main+16>:sub esp,0x1c 0x565561fc <main+19>:call 0x565560f0 <__x86.get_pc_thunk.bx> 0x56556201 <main+24>:add ebx,0x2dff 0x56556207 <main+30>:mov esi,ecx 0x56556209 <main+32>:mov DWORD PTR [ebp-0x1c],0x0[------------------------------------stack-------------------------------------]0000| 0xffffd22c --> 0xffffd250 --> 0x2 0004| 0xffffd230 --> 0x0 0008| 0xffffd234 --> 0xf7f94000 --> 0x1d5d8c 0012| 0xffffd238 --> 0x0 0016| 0xffffd23c --> 0xf7dd79a1 (<__libc_start_main+241>:add esp,0x10)0020| 0xffffd240 --> 0xf7f94000 --> 0x1d5d8c 0024| 0xffffd244 --> 0xf7f94000 --> 0x1d5d8c 0028| 0xffffd248 --> 0x0 [------------------------------------------------------------------------------]Legend: code, data, rodata, valueBreakpoint 1, 0x565561f9 in main ()1: main = {<text variable, no debug info>} 0x565561e9 <main>2: puts = {<text variable, no debug info>} 0xf7e25e40 <puts>gdb-peda$让我们来看看程序的逻辑,程序首先尝试比较参数的数量。它存储在ecx寄存器中并移动到esi,它用于将值与0x2进行比较 0x56556207 <+30>:mov esi,ecx 0x56556209 <+32>:mov DWORD PTR [ebp-0x1c],0x0 0x56556210 <+39>:mov DWORD PTR [ebp-0x24],0x7 0x56556217 <+46>:cmp DWORD PTR [esi],0x2 0x5655621a <+49>:je 0x56556238 <main+79> 0x5655621c <+51>:sub esp,0xc 0x5655621f <+54>:lea eax,[ebx-0x1ff8] 0x56556225 <+60>:push eax 0x56556226 <+61>:call 0x56556040 <printf@plt> 0x5655622b <+66>:add esp,0x10 0x5655622e <+69>:sub esp,0xc 0x56556231 <+72>:push 0x1 0x56556233 <+74>:call 0x56556060 <exit@plt>其伪代码看起来是这样的: if(argc != 2) { printf("Usage: script.exe <key>"); exit(1);} 0x56556238 <+79>:mov eax,DWORD PTR [esi+0x4] 0x5655623b <+82>:add eax,0x4 0x5655623e <+85>:mov eax,DWORD PTR [eax] 0x56556240 <+87>:sub esp,0xc 0x56556243 <+90>:push eax 0x56556244 <+91>:call 0x56556070 <strlen@plt> 0x56556249 <+96>:add esp,0x10 0x5655624c <+99>:cmp eax,0xf 0x5655624f <+102>:jbe 0x5655626d <main+132> 0x56556251 <+104>:sub esp,0xc 0x56556254 <+107>:lea eax,[ebx-0x1fe0] 0x5655625a <+113>:push eax 0x5655625b <+114>:call 0x56556050 <puts@plt> 0x56556260 <+119>:add esp,0x10 0x56556263 <+122>:sub esp,0xc 0x56556266 <+125>:push 0x1 0x56556268 <+127>:call 0x56556060 <exit@plt>其代码是这样的: if(strlen(argv[1]) > 15) { puts("Length of argv[1] too long."); exit(1);}如果你检查这个代码,可以看到有一个循环正在迭代我们输入字符串的每个字符。 0x5655626d <+132>:mov DWORD PTR [ebp-0x20],0x0 0x56556274 <+139>:jmp 0x56556290 <main+167> 0x56556276 <+141>:mov eax,DWORD PTR [esi+0x4] 0x56556279 <+144>:add eax,0x4 0x5655627c <+147>:mov edx,DWORD PTR [eax] 0x5655627e <+149>:mov eax,DWORD PTR [ebp-0x20] 0x56556281 <+152>:add eax,edx 0x56556283 <+154>:movzx eax,BYTE PTR [eax] 0x56556286 <+157>:movsx eax,al 0x56556289 <+160>:add DWORD PTR [ebp-0x1c],eax 0x5655628c <+163>:add DWORD PTR [ebp-0x20],0x1 0x56556290 <+167>:mov eax,DWORD PTR [ebp-0x20] 0x56556293 <+170>:cmp eax,DWORD PTR [ebp-0x24] 0x56556296 <+173>:jl 0x56556276 <main+141> 0x56556298 <+175>:cmp DWORD PTR [ebp-0x1c],0x321 0x5655629f <+182>:jne 0x565562bb <main+210> 0x565562a1 <+184>:call 0x565562d9 <comp_key> 0x565562a6 <+189>:sub esp,0x8 0x565562a9 <+192>:push eax 0x565562aa <+193>:lea eax,[ebx-0x1fc4] 0x565562b0 <+199>:push eax 0x565562b1 <+200>:call 0x56556040 <printf@plt> 0x565562b6 <+205>:add esp,0x10 0x565562b9 <+208>:jmp 0x565562cd <main+228> 0x565562bb <+210>:sub esp,0xc 0x565562be <+213>:lea eax,[ebx-0x1fa2] 0x565562c4 <+219>:push eax 0x565562c5 <+220>:call 0x56556050 <puts@plt> 0x565562ca <+225>:add esp,0x10 0x565562cd <+228>:nop 0x565562ce <+229>:lea esp,[ebp-0xc] 0x565562d1 <+232>:pop ecx 0x565562d2 <+233>:pop ebx 0x565562d3 <+234>:pop esi 0x565562d4 <+235>:pop ebp 0x565562d5 <+236>:lea esp,[ecx-0x4] 0x565562d8 <+239>:ret它到底循环了多少个字符?通常来说,我们的密码长度为7个字符。 [----------------------------------registers-----------------------------------]EAX: 0x6 EBX: 0x56559000 --> 0x3efc ECX: 0x6 EDX: 0xffffd4c6 ("1234567890")ESI: 0xffffd250 --> 0x2 EDI: 0x0 EBP: 0xffffd238 --> 0x0 ESP: 0xffffd210 --> 0xf7f943fc --> 0xf7f95200 --> 0x0 EIP: 0x56556293 (<main+170>:cmp eax,DWORD PTR [ebp-0x24])EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------] 0x56556289 <main+160>:add DWORD PTR [ebp-0x1c],eax 0x5655628c <main+163>:add DWORD PTR [ebp-0x20],0x1 0x56556290 <main+167>:mov eax,DWORD PTR [ebp-0x20]=> 0x56556293 <main+170>:cmp eax,DWORD PTR [ebp-0x24] 0x56556296 <main+173>:jl 0x56556276 <main+141> 0x56556298 <main+175>:cmp DWORD PTR [ebp-0x1c],0x321 0x5655629f <main+182>:jne 0x565562bb <main+210> 0x565562a1 <main+184>:call 0x565562d9 <comp_key>[------------------------------------stack-------------------------------------]0000| 0xffffd210 --> 0xf7f943fc --> 0xf7f95200 --> 0x0 0004| 0xffffd214 --> 0x7 0008| 0xffffd218 --> 0x6 0012| 0xffffd21c --> 0x135 0016| 0xffffd220 --> 0x2 0020| 0xffffd224 --> 0xffffd2e4 --> 0xffffd487 ("/mnt/hgfs/shared/Linux RE/nix_5744af788e6cbdb29bb41e8b0e5f3cd5")0024| 0xffffd228 --> 0xffffd2f0 --> 0xffffd4d1 ("NVM_DIR=/root/.nvm")0028| 0xffffd22c --> 0xffffd250 --> 0x2 [------------------------------------------------------------------------------]Legend: code, data, rodata, value0x56556293 in main ()gdb-peda$ print $ebp-0x24$24 = (void *) 0xffffd214gdb-peda$ x/x 0xffffd2140xffffd214:0x00000007代码看起来是这样的:

用户评论

墨染天下

好文!作为CTF新手,这篇文章让我对Linux逆向工程有了更清晰的理解。特别是文中提到的工具介绍和示例分析,让我受益匪浅。感谢作者的分享!

    有6位网友表示赞同!

话扎心

刚开始接触CTF,感觉逆向工程很头疼,看了这篇文章后,感觉豁然开朗,思路清晰多了,感谢作者!

    有10位网友表示赞同!

沐晴つ

非常棒的入门教程,作者讲解清晰,图文并茂,思路也很清晰。让我对CTF逆向工程有了更深刻的认识。

    有20位网友表示赞同!

非想

文章不错,对于初学者来说很有帮助,但是感觉有些内容还是略微抽象,希望作者能再详细解释一下。

    有19位网友表示赞同!

熟悉看不清

终于找到一篇靠谱的Linux CTF逆向工程入门文章了,作者的讲解思路清晰,示例代码也很好理解,值得推荐!

    有13位网友表示赞同!

把孤独喂饱

文章内容很丰富,涵盖了Linux CTF逆向工程的各个方面,作者也提供了很多实用的工具和技巧,但感觉有点太长了,读起来有点吃力。

    有10位网友表示赞同!

旧事酒浓

这篇文章让我对CTF逆向工程有了新的认识,作者的讲解深入浅出,示例代码也很实用,强烈推荐给所有想学习CTF逆向工程的朋友!

    有8位网友表示赞同!

陌颜幽梦

看了这篇文章后,感觉对Linux逆向工程有了初步了解,但是感觉还是有很多东西需要学习和实践,希望能有更多类似的文章分享。

    有16位网友表示赞同!

青衫负雪

作者的写作风格很幽默,文章内容也很有趣,让我对Linux CTF逆向工程产生了浓厚的兴趣,希望作者能继续分享更多相关内容。

    有18位网友表示赞同!

遗憾最汹涌

感觉作者对逆向工程的理解很深,文章内容也比较专业,但是对于初学者来说可能有点难以理解,希望能有更简单的入门教程。

    有16位网友表示赞同!

命该如此

文章结构清晰,内容完整,作者的讲解思路也很清晰,对入门学习很有帮助,但是感觉缺少一些实战案例,希望能有更多实战经验分享。

    有16位网友表示赞同!

疲倦了

这篇文章让我对Linux CTF逆向工程有了更全面的了解,作者的讲解深入浅出,示例代码也很实用,值得收藏!

    有16位网友表示赞同!

龙吟凤

感觉这篇文章只是简单介绍了Linux CTF逆向工程的基本概念,并没有深入讲解具体的操作方法和技巧,希望作者能写更多进阶教程。

    有16位网友表示赞同!

罪歌

文章内容有点过于基础,对于已经有一定基础的玩家来说可能有点枯燥,希望作者能分享一些更高级的技巧和方法。

    有12位网友表示赞同!

此刻不是了i

作者的写作风格很干练,文章内容也很实用,让我对Linux CTF逆向工程有了更深刻的理解,感谢作者的分享!

    有5位网友表示赞同!

屌国女农

虽然这篇文章比较基础,但对初学者来说很有帮助,作者的讲解清晰,示例代码也很好理解,值得推荐!

    有5位网友表示赞同!

傲世九天

感觉作者对Linux CTF逆向工程的理解很深,文章内容也比较专业,但是对于初学者来说可能有点难以理解,希望作者能写一些更简单的教程。

    有20位网友表示赞同!

黑夜漫长

文章内容很丰富,涵盖了Linux CTF逆向工程的各个方面,作者也提供了很多实用的工具和技巧,但感觉有点太长了,读起来有点吃力。

    有13位网友表示赞同!

虚伪了的真心

这篇文章让我对CTF逆向工程有了新的认识,作者的讲解深入浅出,示例代码也很实用,强烈推荐给所有想学习CTF逆向工程的朋友!

    有15位网友表示赞同!

服从

看了这篇文章后,感觉对Linux逆向工程有了初步了解,但是感觉还是有很多东西需要学习和实践,希望能有更多类似的文章分享。

    有10位网友表示赞同!

标题:Linux CTF 逆向工程入门
链接:https://www.313yx.com//news/sypc/178653.html
版权:文章转载自网络,如有侵权,请联系删除!
资讯推荐
更多
亚丝娜礼包|DNF神秘礼包SAO套装详解,微笑的棺材就是他

这次礼包内容丰富,包含时装、光环、称号、宠物、宝珠、亚丝娜的篮子以及各种消耗品,一起来看看完整的内容。女

2024-08-28
金铲铲之战皮肤原画,金铲铲之战游戏原画

金铲铲之战画之灵强势阵容推荐金铲铲之战画之灵强势阵容怎么搭配?金铲铲之战S11斗射卡莎阵容怎么搭配?金铲铲

2024-08-28
崩坏星穹铁道什么时候上线,崩坏星穹铁道bilibili

崩坏星穹铁道2.2卡池角色及上线时间崩坏星穹铁道2.2卡池角色有哪些?崩坏星穹铁道2.2卡池上线时间是什么时候?

2024-08-28
金铲铲之战s1阵容t0,金铲铲之战s1最佳阵容

金铲铲之战s11低费阵容搭配建议金铲铲之战s11低费阵容有哪些?金铲铲之战s11低费阵容怎么搭配?金铲铲之战s11低

2024-08-28