[b01lers2020]little_engine

[b01lers2020]little_engine

BUUCTF一道简单的逆向

String和Vector的结构逆向:

c++的程序要注意这些复杂的数据类型,否则有些函数的传参操作和运算结果会非常匪夷所思(因为又很多地方是这种复杂结构的引用传递...)

00000000 string struc ; (sizeof=0x28, mappedto_22)
00000000                                         ; XREF: get_input/r
00000000 ptr dq ?                                ; XREF: get_input:loc_12BB/r
00000000                                         ; get_input+41/w ... ; offset
00000008 size dq ?                               ; XREF: get_input+4C/w
00000008                                         ; get_input+5F/r
00000010 buf db 24 dup(?)                        ; XREF: get_input+34/o
00000010                                         ; get_input+55/w ; string(C)
00000028 string ends
00000028
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 vector struc ; (sizeof=0x18, mappedto_23)
00000000                                         ; XREF: main/r
00000000 start_ptr dq ?                          ; XREF: main:loc_12D1/r
00000000                                         ; main+61/r ; offset
00000008 end_ptr dq ?                            ; offset
00000010 max_ptr dq ?                            ; offset
00000018 vector ends
00000018

获取gdb中的内存

加密过程中国,key似乎经历了一些拷贝等额外处理,但是这个处理的结果是固定的。由于我比较懒,所以可以考虑直接去把gdb里面的内存给打印出来:

import gdb

def print_memory_as_python_list(address, size):

    memory = gdb.execute('x/{0}xb {1}'.format(size, address), to_string=True)

    memory_line=memory.split('\n')
    memory_list=[]
    for line in memory_line:
        memory_bytes=line.split(':')[-1:][0].split('\t')[1:]
        for i in memory_bytes:
            memory_list.append(int(i,16))

    #memory_list = '[' + ', '.join(memory.strip().split(':')[1].split()) + ']'
    
    print(memory)
    print(memory_list)
    fd=open('./dump','w')
    fd.write(memory)
    fd.write('\n')
    fd.write(str(memory_list))
    fd.write('\n')

# gdb.Command('print-memory', gdb.COMMAND_DATA, print_memory_as_python_list)
print_memory_as_python_list(0x55a783f2a2f0 ,0x420-0x2f0)

使用时,把想打印的内存起始地址和打印字节数写进去,在gdb里面执行以下指令即可

source ./print_memory.py

解密

普通的异或加密,唯一要注意的就是key会不断变动,使用python的时候记得处理一下溢出的情况。


encoded_flag=[225, 230, 208, 74, 242, 195, 126, 170, 230, 252, 66, 178, 242, 181, 1, 180, 236, 125, 57, 32, 239, 192, 78, 19, 200, 47, 103, 170, 149, 121, 107, 245, 242, 6, 65, 121, 216, 53, 249, 200, 142, 222, 136, 81, 172, 76, 240, 129, 224, 244, 238, 20, 173, 241, 37, 189, 130, 124, 98, 48, 165, 248, 128, 43, 121, 133, 42, 248, 110, 90, 174, 203, 24, 58, 162, 208, 9, 197, 140, 93, 61, 52, 107, 249, 59, 114, 75, 14, 74, 195, 113, 83, 225, 233, 7, 187, 193, 26, 231, 7, 143, 27, 117, 116, 185, 142, 93, 46, 194, 246, 23, 59, 82, 237, 215, 189, 94, 233, 118, 99, 114, 226, 234, 137, 81, 215, 79, 52, 220, 57, 213, 88, 146, 217, 210, 210, 170, 105, 241, 191, 144, 118, 225, 156, 57, 13, 12, 179, 64, 6, 72, 218, 39, 213, 30, 184, 74, 148, 76, 152, 196, 138, 104, 168, 151, 94, 100, 249, 192, 88, 247, 2, 114, 141, 59, 136, 24, 20, 236, 143, 66, 112, 12, 11, 150, 102, 34, 142, 247, 88, 1, 46, 197, 220, 75, 192, 113, 244, 218, 230, 61, 115, 136, 125, 228, 145, 31, 117, 144, 112, 214, 12, 167, 9, 124, 242, 90, 78, 161, 9, 12, 81, 60, 186, 168, 100, 56, 45, 140, 0, 136, 227, 111, 234, 119, 144, 116, 57, 170, 86, 241, 168, 110, 128, 202, 61, 158, 105, 164, 105, 72, 242, 10, 44, 247, 51, 23, 15, 92, 242, 138, 229, 47, 85, 165, 159, 139, 101, 84, 118, 224, 100, 238, 157, 155, 45, 155, 95, 114, 127, 59, 217, 223, 5, 105, 240, 159, 240, 163, 140, 230, 205, 239, 180, 188, 68, 84, 62, 227, 68, 0, 0, 0, 0]

flag=[]
key=0x91
for i in range(0x4b):
	flag.append(encoded_flag[i*4]^key)
	v=(key+i)
	key=(v+v//0xff)
	key=key&0xff

for i in flag:
	print(chr(i),end='')
print("")

posted @ 2023-09-12 19:18  Jmp·Cliff  阅读(72)  评论(0编辑  收藏  举报