逆向 Writeup:西湖论剑2020逆向第一题Cellular

本文介绍了一种解决编程挑战的方法,涉及对程序的黑盒测试和路径搜索算法。通过在OD中修改目标程序,以观察循环次数来判断路径是否正确,并使用Python脚本生成和测试可能的输入字符串。最终,通过逐步试错找到正确路径——'RLRLLRLLLRRLLRLLRLRLLRLLR',并计算其MD5散列值以获得最终答案。解题过程中展示了路径搜索算法的工作原理和一系列尝试的路径组合。
摘要由CSDN通过智能技术生成

摘要

  1. 题目为“蜜蜂如何筑巢”,问题的实质是寻找路径。应该将程序视为黑盒。刚开始解题思路不对,一直试图理清代码中的逻辑。
  2. 解答的方法是尝试将各种由‘L’和‘R'组合的长为25的字符串作为输入,直到打印信息“Congratulations”。可采用遍历法,或逐步试错法。本篇采用后者。
  3. 本篇方法概括:
    3.1 在OD中修改源码,改变关键函数CheckFlag的返回值为其中的大循环的循环次数(通过该次数可得知当前前行方向正确与否,从而调整路径方向);修改打印部分代码,使其打印的信息能反映刚刚说的循环次数。
    3.2 写python脚本,生成输入字符串,借由其subprocess模块将字符串传给Cellular程序进行判断。通过逐步试错找到正确路径。
  4. 如果有好的测试工具的话也许就不用自己写脚本这么麻烦了。但目前没找着。

题目概括

程序界面如下。需要输入’L’和’R’组成的字符串。
在这里插入图片描述

使用IDA解析,其主函数如下图。
在这里插入图片描述
关键函数CheckFlag的逻辑如下图。
在这里插入图片描述
在用OD调试时看到其中有类似链表的数据结构。
在这里插入图片描述

对于CheckFlag函数其实只要大概明白其意思即可,无需深究。其中for循环的i值会在解题时用到。

解题过程

修改原始程序

将程序拖入OD,找到CheckFlag函数结尾返回部分,修改其返回值为for循环的i值。
在这里插入图片描述

修改数据段,添加27个可打印的字符。
在这里插入图片描述

修改主函数中打印”Congratulations“信息的代码,使用CheckFlag返回的数值作为索引,从上一步添加的数据中按索引找一个字符并打印。这个字符将在下一步起判断作用。
在这里插入图片描述

编写搜索正确字符串的python脚本

# 定义一个函数,用于运行Cellular程序、接受输入、获取程序在标准输出流打印的信息.
def test_path(ans):
    path = "C:/Users/bohan/ctffiles/cellular/Cellular_pad2.exe"
    cellular = subprocess.Popen([path], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    output = cellular.communicate(ans.encode())[0]
    correct_len = output[output.index(b'Path') + 5] - ord('a')
    return correct_len

用于搜索路径的算法如下:

arr_len = 25
bit_arr = [0 for _ in range(arr_len)]
bit_arr
cur_index = 0
def select_path(path_is_adapted):
	'''path_is_adapted为True时则继续前进,为False则需改当前cur_index所指处的方向'''
    global cur_index
    if cur_index < arr_len and path_is_adapted:
        cur_index += 1
    elif cur_index > -1 and not path_is_adapted:
        bit_arr[cur_index] += 1  # 更改方向
        while bit_arr[cur_index] > 1 and cur_index > -1:  # 如果左右两个方向都试过了,则要向前移动,改前面的方向
#             print("cur_index ", cur_index)
            bit_arr[cur_index] = 0
            cur_index -= 1  # 向前移动指针
            bit_arr[cur_index] += 1  # 然后更改方向
            
    return cur_index

def get_cur_path():
    arr = bit_arr[0:cur_index + 1]
    lr = ['L', 'R']
    path_str = ''.join([lr[i] for i in arr])
    return arr, path_str

测试部分:

correct_len = 0
while correct_len != -49:  # correct_len为-49(字符'a'和字符’0‘的ascii码值相减所得)时表明打印了字符零,也即找到了正确路径
    bit_path, path_str = get_cur_path()
    print(bit_path, path_str)
    try:
        correct_len = test_path(path_str)
        print(correct_len)
        if correct_len == len(path_str) and correct_len != 25:
            print("T")
            select_path(True)
        else:
            print("F")
            select_path(False)
    except:
        print("发生异常")
        select_path(False)
        
    if not path_str:
        print("无路径")
        break

运行后打印的情况如下(下图为打印结果的最后几行):
在这里插入图片描述从上图知最终路径为:‘RLRLLRLLLRRLLRLLRLRLLRLLR’。当然最后还得用md5计算其散列值,才得到最终flag。

附一个搜索过程中列出的所有路径,方便理解上述路径搜索算法:

LL
LR
R
RL
RLL
RLLL
RLLR
RLLRL
RLLRLL
RLLRLLL
RLLRLLR
RLLRLLRL
RLLRLLRR
RLLRLLRRL
RLLRLLRRR
RLLRLR
RLLRR
RLLRRL
RLLRRLL
RLLRRLLL
RLLRRLLLL
RLLRRLLLLL
RLLRRLLLLR
RLLRRLLLLRL
RLLRRLLLLRR
RLLRRLLLLRRL
RLLRRLLLLRRR
RLLRRLLLR
RLLRRLLR
RLLRRLLRL
RLLRRLLRR
RLLRRLLRRL
RLLRRLLRRR
RLLRRLR
RLLRRR
RLLRRRL
RLLRRRLL
RLLRRRLLL
RLLRRRLLLL
RLLRRRLLLLL
RLLRRRLLLLLL
RLLRRRLLLLLR
RLLRRRLLLLLRL
RLLRRRLLLLLRR
RLLRRRLLLLLRRL
RLLRRRLLLLLRRR
RLLRRRLLLLR
RLLRRRLLLR
RLLRRRLLLRL
RLLRRRLLLRR
RLLRRRLLLRRL
RLLRRRLLLRRR
RLLRRRLLR
RLLRRRLR
RLLRRRR
RLR
RLRL
RLRLL
RLRLLL
RLRLLLL
RLRLLLLL
RLRLLLLR
RLRLLLLRL
RLRLLLLRLL
RLRLLLLRLR
RLRLLLLRLRL
RLRLLLLRLRR
RLRLLLLRLRRL
RLRLLLLRLRRR
RLRLLLLRR
RLRLLLLRRL
RLRLLLLRRLL
RLRLLLLRRLR
RLRLLLLRRR
RLRLLLLRRRL
RLRLLLLRRRLL
RLRLLLLRRRLLL
RLRLLLLRRRLLR
RLRLLLLRRRLR
RLRLLLLRRRR
RLRLLLR
RLRLLLRL
RLRLLLRLL
RLRLLLRLR
RLRLLLRLRL
RLRLLLRLRR
RLRLLLRLRRL
RLRLLLRLRRR
RLRLLLRR
RLRLLLRRL
RLRLLLRRLL
RLRLLLRRLR
RLRLLLRRR
RLRLLLRRRL
RLRLLLRRRLL
RLRLLLRRRLLL
RLRLLLRRRLLR
RLRLLLRRRLR
RLRLLLRRRR
RLRLLR
RLRLLRL
RLRLLRLL
RLRLLRLLL
RLRLLRLLLL
RLRLLRLLLLL
RLRLLRLLLLLL
RLRLLRLLLLLR
RLRLLRLLLLLRL
RLRLLRLLLLLRR
RLRLLRLLLLLRRL
RLRLLRLLLLLRRLL
RLRLLRLLLLLRRLLL
RLRLLRLLLLLRRLLR
RLRLLRLLLLLRRLLRL
RLRLLRLLLLLRRLLRLL
RLRLLRLLLLLRRLLRLLL
RLRLLRLLLLLRRLLRLLR
RLRLLRLLLLLRRLLRLLRL
RLRLLRLLLLLRRLLRLLRLL
RLRLLRLLLLLRRLLRLLRLR
RLRLLRLLLLLRRLLRLLRLRL
RLRLLRLLLLLRRLLRLLRLRLL
RLRLLRLLLLLRRLLRLLRLRLLL
RLRLLRLLLLLRRLLRLLRLRLLR
RLRLLRLLLLLRRLLRLLRLRLLRL
RLRLLRLLLLLRRLLRLLRLRLLRR
RLRLLRLLLLLRRLLRLLRLRLR
RLRLLRLLLLLRRLLRLLRLRR
RLRLLRLLLLLRRLLRLLRR
RLRLLRLLLLLRRLLRLR
RLRLLRLLLLLRRLLRR
RLRLLRLLLLLRRLR
RLRLLRLLLLLRRR
RLRLLRLLLLR
RLRLLRLLLLRL
RLRLLRLLLLRR
RLRLLRLLLLRRL
RLRLLRLLLLRRLL
RLRLLRLLLLRRLLL
RLRLLRLLLLRRLLR
RLRLLRLLLLRRLLRL
RLRLLRLLLLRRLLRLL
RLRLLRLLLLRRLLRLLL
RLRLLRLLLLRRLLRLLR
RLRLLRLLLLRRLLRLLRL
RLRLLRLLLLRRLLRLLRLL
RLRLLRLLLLRRLLRLLRLR
RLRLLRLLLLRRLLRLLRLRL
RLRLLRLLLLRRLLRLLRLRLL
RLRLLRLLLLRRLLRLLRLRLLL
RLRLLRLLLLRRLLRLLRLRLLR
RLRLLRLLLLRRLLRLLRLRLLRL
RLRLLRLLLLRRLLRLLRLRLLRLL
RLRLLRLLLLRRLLRLLRLRLLRLR
RLRLLRLLLLRRLLRLLRLRLLRR
RLRLLRLLLLRRLLRLLRLRLR
RLRLLRLLLLRRLLRLLRLRR
RLRLLRLLLLRRLLRLLRR
RLRLLRLLLLRRLLRLR
RLRLLRLLLLRRLLRR
RLRLLRLLLLRRLR
RLRLLRLLLLRRR
RLRLLRLLLR
RLRLLRLLLRL
RLRLLRLLLRR
RLRLLRLLLRRL
RLRLLRLLLRRLL
RLRLLRLLLRRLLL
RLRLLRLLLRRLLR
RLRLLRLLLRRLLRL
RLRLLRLLLRRLLRLL
RLRLLRLLLRRLLRLLL
RLRLLRLLLRRLLRLLR
RLRLLRLLLRRLLRLLRL
RLRLLRLLLRRLLRLLRLL
RLRLLRLLLRRLLRLLRLR
RLRLLRLLLRRLLRLLRLRL
RLRLLRLLLRRLLRLLRLRLL
RLRLLRLLLRRLLRLLRLRLLL
RLRLLRLLLRRLLRLLRLRLLR
RLRLLRLLLRRLLRLLRLRLLRL
RLRLLRLLLRRLLRLLRLRLLRLL
RLRLLRLLLRRLLRLLRLRLLRLLL
RLRLLRLLLRRLLRLLRLRLLRLLR
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值