ida mips插件安装+攻防世界ereere题解
1383304434560949 发表于 山东 CTF 1580浏览 · 2024-07-12 05:22

第一次写,求多多支持
首先是插件安装
由于网上搜到的资料比较杂乱,且尝试了几次后报错,因此分享一下成功安装运行的过程
mips插件安装
下载地址:https://github.com/fuzzywalls/ida
下载以后如图所示:

首先,打开plugins文件夹,然后找出自己ida7版本的根目录下的plugins文件夹:

将下载的ida-master的plugins文件夹下的所有py文件,复制到自己ida7版本的根目录下的plugins文件夹
然后再找到下载的ida-master下的scripts文件夹,将整个文件夹复制到自己ida7版本的根目录:


复制完成后刷新,在刚刚复制的各种py文件中,找到ida-master\plugins\mipsrop\mipsrop.py
由于Python2和Python3的版本兼容问题,所以需要修改一下代码保证正常运行

第82行:
from shims import ida_shims
改为
import ida_shims
否则会出现No module named 'shims'这个错误提示

剩下的问题就是print需要打括号

第218行:
print line
改为
print (line)

第236行:
print "MIPS ROP Finder activated, found %d controllable jumps " \
"between 0x%.8X and 0x%.8X" % (len(self.controllable_jumps),
self.start, self.end)
改为
print ("MIPS ROP Finder activated, found %d controllable jumps " \
"between 0x%.8X and 0x%.8X" % (len(self.controllable_jumps),
self.start, self.end))

第240行:
print "No ROP gadgets found!"
改为
print ("No ROP gadgets found!")

第521行:
def _print_gadgets(self, gadgets):
if gadgets:
print gadgets[0].header()
for gadget in gadgets:
print str(gadget)
if gadgets:
print gadgets[0].footer()
print "Found %d matching gadgets" % (len(gadgets))
改为(共四处)
def _print_gadgets(self, gadgets):
if gadgets:
print (gadgets[0].header())
for gadget in gadgets:
print (str(gadget))
if gadgets:
print (gadgets[0].footer())
print ("Found %d matching gadgets" % (len(gadgets)))

第654行
print "Skipping gadget at 0x%X" % ea
改为
print ("Skipping gadget at 0x%X" % ea)

第658行:
print "No ROP gadgets found!"
改为
print ("No ROP gadgets found!")

第720行:
print delim
print line_fmt % \
(headings['name'], headings['offset'], headings['summary'])
print delim
改为(共三处)
print (delim)
print (line_fmt % \
(headings['name'], headings['offset'], headings['summary']))
print (delim)

第737行:
if line_count == 0:
print line_fmt % (marked_comment, offset, line)
else:
print line_fmt % ('', '', line)
改为(共两处)
if line_count == 0:
print (line_fmt % (marked_comment, offset, line))
else:
print (line_fmt % ('', '', line))

第744行:
print delim
改为
print (delim)

767-800行:
print ""
print "mipsrop.find(instruction_string)"
print delim
print self.find.doc

print ""
    print "mipsrop.system()"
    print delim
    print self.system.__doc__

    print ""
    print "mipsrop.doubles()"
    print delim
    print self.doubles.__doc__

    print ""
    print "mipsrop.stackfinders()"
    print delim
    print self.stackfinders.__doc__

    print ""
    print "mipsrop.tails()"
    print delim
    print self.tails.__doc__

    print ""
    print "mipsrop.set_base()"
    print delim
    print self.set_base.__doc__

    print ""
    print "mipsrop.summary()"
    print delim
    print self.summary.__doc__

改为(懒得数多少处了,反正基本上每行都改)
print ("")
print ("mipsrop.find(instruction_string)")
print (delim)
print (self.find.doc)

print ("")
    print ("mipsrop.system()")
    print (delim)
    print (self.system.__doc__)

    print ("")
    print ("mipsrop.doubles()")
    print (delim)
    print (self.doubles.__doc__)

    print ("")
    print ("mipsrop.stackfinders()")
    print (delim)
    print (self.stackfinders.__doc__)

    print ("")
    print ("mipsrop.tails()")
    print (delim)
    print (self.tails.__doc__)

    print ("")
    print ("mipsrop.set_base()")
    print (delim)
    print (self.set_base.__doc__)

    print ("")
    print ("mipsrop.summary()")
    print (delim)
    print (self.summary.__doc__)

OK改完以后记得保存,改的一定是已经拷进自己ida7根目录下的文件!!!
打开ida
左上角file-script command

红框部分选Python
蓝框部分输入:
import mipsrop
mipsrop = mipsrop.MIPSROPFinder()
然后点运行,即可安装运行成功
下次使用的时候只需要左上角edit-plugins-MIPS ROP Finder即可

运行完成后,就可以查看反编译的函数了
由于函数名没有main,所以我们只通过函数名找主函数就比较困难,shift+F12找到所有的字符串,我们发现了几个非常“main”的字符

"ZYXWVUTSRQPONMLKJIHGFEDCBAabcdefghijklmnopqrstuvwxyz/+9876543210"和"ScDZC1cNDZaxnh/2eW1UdqaCiJ0ijRIExlvVEgP43rpxoxbYePBhpwHDPJ=="可以初步判断涉及了换表的base64,因此操作基本上就围绕"ScDZC1cNDZaxnh/2eW1UdqaCiJ0ijRIExlvVEgP43rpxoxbYePBhpwHDPJ=="展开,因此跟进后Ctrl+x寻找交叉引用:

基本找到了主函数(根据猜测把几个函数名称修改了一下方便理解)
sub_41A6E0基本上可以理解为Python中的len()和c中的strlen()但是也有不同(以下是对sub_41A6E0的简单分析,可以忽略)
//
char __fastcall sub_41A6E0(char a1) 定义了一个函数 sub_41A6E0,使用 __fastcall 调用约定,接受一个字符指针 a1 作为参数,并返回一个字符指针。

char *v1; // $v0 声明了一个字符指针 v1 用于存储原始输入指针的值。

v1 = a1; 将输入指针的值赋给 v1。

if ( ((unsigned __int8)a1 & 3) == 0 ) 检查输入指针 a1 是否4字节对齐。如果对齐,继续执行搜索优化。

while ( 1 ) 开始一个无限循环,用于搜索字符串。

LABEL_7: 是一个标签,用于跳转。

if ( (((_DWORD )a1 - 16843009) & ~(_DWORD )a1 & 0x80808080) != 0 ) 这是一个条件判断,用于检查当前4字节是否包含空字符。16843009 是一个特定的32位值,用于与当前4字节进行异或操作,如果结果与 0x80808080 进行位与操作后不为0,则说明这4个字节中至少有一个是空字符。

if ( !a1 ) return (char )(a1 - v1); 如果第一个字符是空字符,返回从原始指针 v1 开始到当前位置的长度。

接下来的三个 if 语句分别检查第二个、第三个和第四个字符是否是空字符,并返回相应的长度。

a1 += 4; 如果当前4字节中没有空字符,将指针向前移动4个字节。

if ( !*a1++ ) 如果在非对齐的情况下遇到空字符,返回从 v1 开始到当前位置的长度。

while ( 1 ) 另一个无限循环,用于在非对齐情况下搜索空字符。

if ( ((unsigned __int8)a1 & 3) == 0 ) goto LABEL_7; 如果指针再次对齐到4字节边界,跳转到 LABEL_7 继续使用优化算法。

if ( !a1 ) return (char )(a1 - v1); 如果在非对齐搜索中遇到空字符,返回从 v1 开始到当前位置的长度。

++a1; 如果当前字符不是空字符,将指针向前移动1个字节。
//
跟进sub_4009DC-sub_400864
看到256本能的觉得是rc4算法(当然不能只靠猜)

分析可知这个函数是rc4初始化S盒,我们也因此找到密钥"flag{123321321123badbeef012}"
//
BOOL sub_400864() 定义了一个返回布尔值(BOOL)的函数 sub_400864。

定义了几个局部变量:result 用于存储最终结果,i 和 j 用于循环计数,v3 和 v4 用于计算,v5 用于存储临时值。

for ( i = 0; i < 256; ++i ) byte_4A0860[i] = i; 这个循环初始化了一个大小为 256 的数组 byte_4A0860,数组的每个元素值从 0 到 255。

v4 = 0; 初始化变量 v4 为 0。

LOBYTE(v3) = 0; 将变量 v3 的最低字节初始化为 0。这里 LOBYTE 宏用于提取或设置一个 DWORD 的最低字节。

for ( j = 0; ; ++j ) 开始一个无限循环,使用变量 j 作为索引。

result = j < 256; 将 result 设置为一个布尔值,当 j 小于 256 时为真。

if ( j >= 256 ) break; 如果 j 大于或等于 256,退出循环。这保证了循环不会无限进行。

v5 = byte_4A0860[j]; 将数组 byte_4A0860 中索引为 j 的元素值赋给 v5。

v3 = (unsigned int8)(v5 + v3 + aFlag1233213211[v4]); 计算一个新的索引 v3,它是 v5、v3 的当前值和 aFlag1233213211 数组中索引为 v4 的元素值的和。这里使用了模 256 运算,因为 v3 是通过强制转换为 unsigned int8 来确保结果在 0 到 255 范围内。

byte_4A0860[j] = byte_4A0860[v3]; 将 byte_4A0860 数组中索引为 v3 的元素值与索引为 j 的元素交换。

byte_4A0860[v3] = v5; 将 v5 赋值给 byte_4A0860 数组中索引为 v3 的位置。

if ( ++v4 >= (unsigned int)sub_41A6E0(aFlag1233213211) ) v4 = 0; 每次循环后 v4 加 1,如果 v4 大于或等于 aFlag1233213211 数组的长度,v4 重置为 0。这里 sub_41A6E0 函数用于获取数组 aFlag1233213211 的长度。

return result; 函数返回 result,它是一个布尔值,表示循环是否成功完成。

//
esc返回我们再分析外层函数

//
BOOL fastcall sub_4009DC(char *a1) 定义了一个使用 fastcall 调用约定的函数 sub_4009DC,它接受一个字符指针 a1 作为参数,并返回一个布尔值。

定义了局部变量 result 来存储函数的最终结果,i 作为循环计数器,v3 和 v4 用于在伪随机生成过程中的索引,v5 用于临时存储字节。

sub_400864(a1); 调用之前分析过的 sub_400864 函数,它初始化一个排列数组 byte_4A0860,这是 RC4 算法中生成密钥流的第一步。

v4 = 0; 和 v3 = 0; 初始化 v3 和 v4 为 0,这两个变量将用于生成密钥流。

for ( i = 0; ; ++i ) 开始一个无限循环,用于生成密钥流并加密或解密数据。

result = i < sub_41A6E0(a1); 设置 result 为一个布尔值,如果 i 小于 a1 字符串的长度,则为真。

if ( !result ) break; 如果 result 为假(即 i 大于或等于 a1 的长度),则退出循环。

v3 = (v3 + 1) % 256; 更新 v3 的值,实现循环增量,并确保它在 0 到 255 范围内。

v4 = (byte_4A0860[v3] + v4) % 256; 根据 v3 的值更新 v4,确保它也在 0 到 255 范围内。

v5 = byte_4A0860[v3]; 将 byte_4A0860 数组中索引为 v3 的元素值存储在 v5 中。

byte_4A0860[v3] = byte_4A0860[v4]; 交换 byte_4A0860 数组中 v3 和 v4 索引的元素。

byte_4A0860[v4] = v5; 将 v5 的值放回 byte_4A0860 数组的 v4 索引处。

a1[i] ^= byte_40A6E0[(unsigned __int8)(byte_4A0860[v3] + byte_4A0860[v4])]; 使用 byte_4A0860 数组生成的密钥流对 a1 中的字节进行异或操作。这里 byte_40A6E0 应该是一个错误,应该是 byte_4A0860。这个操作生成了 RC4 的输出,即密钥流与明文的异或结果,用于加密或解密。

return result; 函数返回 result,表示循环是否成功完成。
//
另附rc4加密的过程便于理解:
1.初始化过程:
初始化S盒:按照升序,给每个字节赋值,一共256个字节,赋值从0到255

初始化T盒:用户输入部分,如果输入长度小于256个字节,则进行重复,直到填满
然后,根据j=(j+T[i]+S[i])%256求出新的j,并与S[i]进行交换,这样保证了S盒的不断变化

void rc4_init(unsigned char*s,unsigned char*key,unsigned long Len)
{
int i=0,j=0;
char k[256]={0};
unsigned char tmp=0;
for(i=0;i<256;i++)
{
s[i]=i;
k[i]=key[i⁹%Len];
}
for(i=0;i<256;i++)
{
j=(j+s[i]+k[i])%256;
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}

2.加密过程:
j = ( j + S[i] ) % 256求出新的j,并与S[i]进行交换
t = (S[j] + S[i] ) % 256求出t
再通过明文与S[t]异或得到密文

void rc4_crypt(unsigned char*s,unsigned char*Data,unsigned long Len)
{
int i=0,j=0,t=0;
unsigned long k=0:
unsigned char tmp
for(k=0;k<Len;k++)
{
i=(i+1)%256;j=(j+s[i])%256;tmp=s[i];
s[i]=s[j];
s[j]=tmp;
t=(s[i]+s[j])%256;
Data[k]=s[t];
}

再看剩下的函数sub_400550:(经典的base64换表)

sub_41A1E0是比较函数,因此理顺一下:
输入→rc4(key="flag{123321321123badbeef012}")→base64换表→"ScDZC1cNDZaxnh/2eW1UdqaCiJ0ijRIExlvVEgP43rpxoxbYePBhpwHDPJ=="
所以想要得到输入了什么,逆过来就行,推荐一个比较好用的网站cyberchef

题目附件如下

附件:
  • 127b4261-e1d7-4f50-a30a-ab3357502203 (1).zip 下载
0 条评论
某人
表情
可输入 255
目录