hackme inndy reverse rc87cipher writeup

话说这题真的挺难折腾出来的

首先这个程序是有upx壳的

但是这个壳被魔改了,关键的信息都被删除了,在google搜了半天linux upx upack 都找不到什么有用的信息

有两条路,一条是修复关键信息,一条路是像windows那些程序那样手动脱壳脱下来

两条路其实都试了一下,不过最终行得通的是第二条路

这里说下第一条路,如果你们有兴趣的话,可以去试试

首先作者把0xB4~0xB7处的UPX!填充为0xff了,然后把代码段有一个copyright的声明用nop给填掉了(话说查的时候看到upx的github上有人po了rctf的一道题,然后被upx的人吐槽copyright被改了,违反了规则hhhhh

然后去看了下github上upx的源码,源码里有一个函数 canUnpack,这里貌似是会检查文件尾的32个字节,具体的可以去看源码,然后如果想修的话,找一个正常的upx程序,把文件尾的32个字节复制上去,然后根据报错信息来慢慢改

然后来说下第二条路
首先upx壳在解压的过程中是不会加载so的,只会一直用syscall,这里用到一个神器,radare2(用得好爽

然后upx壳的规律是,最后一个syscall肯定是munmap,所以只要试一下就知道oep在哪里了

我这里写个简单的radare2脚本来找oep
对于静态链接的程序

9dcs
ds

对于动态链接的程序

15dsc
ds

这样就能找到oep,或者可以参考一下别人找oep的脚本
https://asciinema.org/a/35005

找到oep之后,也是按照上面链接里面的方式dump下来
dump下来之后用ida解析一波,有可能是我不会dump吧。。。很多函数都没识别出来,但是无所谓,大概都能猜出来

这里的oep是_start,所以最后那个call是__libc_start_main,所以第一个参数,也就是rdi,就是真正的main的地址

这里大概说下程序做了什么
这个程序只实现了加密的功能

加密的过程是,首先读取8个byte随机字符
然后根据这8个byte的字符来生成sbox

之后把这8个byte写到加密文件的开头

然后每次从被加密的文件读一个字符,就用password中的一个字符来对sbox操作一波

这里有rc87和rc87.enc,于是就可以暴力dfs破出password,这里的password其实就是flag

最后给出解题的脚本


f = open('./rc87', 'rb')
rc87_data = f.read()
f.close()

f = open('./rc87.enc', 'rb')
rc87enc_data = f.read()
f.close()


rc87enc_random_seed = rc87enc_data[:8]
rc87enc_data = rc87enc_data[8:]


def sbox_loop(v1, v2, sbox):
    for q in range(36):
        v2 = (13 * (~v2)) & 0xff
        v1 = (17 * (~v1)) & 0xff
        t1 = sbox[v1]
        t2 = sbox[v2]
        sbox[v1] = t2
        sbox[v2] = t1


def generate_sbox(seed):
    sbox = []
    for i in range(256):
        sbox.append(i)

    for i in range(8):
        sbox_loop(seed[i], i, sbox)
    return sbox


rc87enc_sbox = generate_sbox(rc87enc_random_seed)

password = ''
password_length = 40

def get_xor_value(tsbox):
    v9 = 0xdeadbeef
    for w in range(256):
        v11 = tsbox[w]
        v9 = 821091 * v11 ^ 23159 * v9
        v9 &= 0xffffffff
    return v9


def find_password(pas, tsbox):
    if len(pas) >= password_length:
        if(pas[39]=='}'):
           return [pas]
        else:
           return []
    possible_pas = []
    for i in range(32,127):
        ttsbox = [i for i in tsbox]
        sbox_loop(i, len(pas), ttsbox)
        v9 = get_xor_value(ttsbox)
        v15 = (17 * rc87_data[len(pas)]) ^ v9
        v15 &= 0xff
        if v15 == rc87enc_data[len(pas)]:
            possible_pas += find_password(pas + chr(i), ttsbox)
    return possible_pas


print(find_password('', rc87enc_sbox))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值