CTF

二进制分析实战第五章(2)

Posted by Kody Black on September 11, 2023

第五章 Linux二进制分析

在提交第一题后,会生成第二题

$ ./oracle 84b34c124b2ba5ca224af8e33b077e9e
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 1 completed, unlocked lvl2         |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint

第二题:分析lvl2文件

$ file lvl2 
lvl2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=457d7940f6a73d6505db1f022071ee7368b67ce9, stripped
$ ./lvl2
f6
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
4f
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
6c
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
6c
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
81
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
81
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
88
binary@binary-VirtualBox:~/code/chapter5/second$ ./lvl2
d3

多次执行lvl2,发现每次结果不一样

$ ltrace ./lvl2
__libc_start_main(0x400500, 1, 0x7ffda5435098, 0x400640 <unfinished ...>
time(0)                                                                                        = 1690701220
srand(0x64c60da4, 0x7ffda5435098, 0x7ffda54350a8, 0)                                           = 0
rand(0x7fcac6f73620, 0x7ffda5434f7c, 0x7fcac6f730a4, 0x7fcac6f7311c)                           = 0x5e2391d
puts("6c"6c
)                                                                                     = 3
+++ exited (status 0) +++

发现lvl2调用了随机函数,想到可以利用LD_PRELOAD劫持rand函数,让其不再随机

编写unrandom.c如下:

int rand(){
    return 0;
}

编写shell脚本如下:

#!/bin/bash

current_val=0
export LD_PRELOAD='./unrandom.so'

for ((i=1; i<=20; i++))
do

    # 编译生成共享库
    gcc -shared -fPIC unrandom.c -o unrandom.so

    # 等待0.1s
    sleep 1
    
    # 执行lvl2程序
    ./lvl2

    # 修改unrandom.c中rand函数的返回值为前一次的返回值加一
    sed -i "s/return $current_val;/return $((current_val + 1));/" unrandom.c

    # current_val加一
    current_val=$((current_val + 1))
    
done

# 修改unrandom.c中rand函数的返回值为0
sed -i "s/return $current_val;/return 0;/" unrandom.c

运行go.sh,结果如下:

$ ./go.sh 
03
4f
c4
f6
a5
36
f2
bf
74
f8
d6
d3
81
6c
df
88
03
4f
c4
f6

发现一共16个值,把前16个连起来得到flag=034fc4f6a536f2bf74f8d6d3816cdf88

$ ./oracle 034fc4f6a536f2bf74f8d6d3816cdf88
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Level 2 completed, unlocked lvl3         |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Run oracle with -h to show a hint

成功!

另外,这些字符串其实可以直接找到:

$ objdump -s --section .rodata lvl2 

lvl2:     file format elf64-x86-64

Contents of section .rodata:
 4006c0 01000200 30330034 66006334 00663600  ....03.4f.c4.f6.
 4006d0 61350033 36006632 00626600 37340066  a5.36.f2.bf.74.f
 4006e0 38006436 00643300 38310036 63006466  8.d6.d3.81.6c.df
 4006f0 00383800                             .88.           

放入ida pro,反编译反汇编后的代码如下:

16944420708901694442070652.png

查看对象s:

16944420879021694442086961.png

跳转到4006C4即可找到字符串内容

16944421029021694442102728.png