babymips上

主要核心代码

var_10= -0x10
var_8= -8
var_4= -4
arg_0=  0addiu   $sp, -0x28
sw      $ra, 0x28+var_4($sp)
sw      $fp, 0x28+var_8($sp)
move    $fp, $sp
sw      $a0, 0x28+arg_0($fp)
li      $v0, 5
sw      $v0, 0x28+var_10($fp)
b       loc_400910
nop
loc_400910:              # s
lw      $a0, 0x28+arg_0($fp)
jal     strlen
nop
move    $v1, $v0
lw      $v0, 0x28+var_10($fp)
nop
sltu    $v0, $v1
bnez    $v0, loc_400814
nop

第六行代码:

li      $v0, 5
sw      $v0, 0x28+var_10($fp)

把5塞到v0寄存器里面,然后v0里面的值塞到0x28+var_10($fp)这个内存单元

jal     strlen

这个函数调用完成后,返回值直接放在v0寄存器中,紧接着

move    $v1, $v0

v0赋值给v1,即把返回值放在v1里面,

lw      $v0, 0x28+var_10($fp)

取出内存单元中的5放在v0里面。然后来两个比较

sltu    $v0, $v1
bnez    $v0, loc_400814


BENZ R1,NAME;//R1!=0,程序跳转,以NAME为偏移地址
v1即是字符串长度。
v1>5则跳,v1<=5则不跳(因为前面已经判断"Q|j{g"这五个的原因吧)即选择跳

loc_400814:
lw      $v0, 0x28+var_10($fp)
nop
andi    $v0, 1
beqz    $v0, loc_400898
nop

把5取出来,然后和1进行与操作
重点:和1进行与操作,这样是为了判断这个字符的位置是奇数还是偶数,奇数的话与操作也就是非0,偶数的话,与操作后为0),
BEQZ R1,NAME;//R1=0,程序跳转到,以NAME为偏移地址

这里两处都应该看,因为奇偶数位都在变,得分析他们的变化。

偶数位

loc_400898:
lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)
nop
addu    $v0, $v1, $v0
lb      $v0, 0($v0)
nop
sll     $v0, 2
sll     $a0, $v0, 24
sra     $a0, 24
lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)
nop
addu    $v0, $v1, $v0
lb      $v0, 0($v0)
nop
sra     $v0, 6
sll     $v1, $v0, 24
sra     $v1, 24
lw      $v0, 0x28+var_10($fp)
lw      $a1, 0x28+arg_0($fp)
nop
addu    $v0, $a1, $v0
or      $v1, $a0, $v1
sll     $v1, 24
sra     $v1, 24
sb      $v1, 0($v0)
lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)

第一行把位数取出来,第二行把参数取出来,因为我们前面传参的时候传的时字符串的地址。
所以v0里面是位数,v1里面是字符串首地址。

addu    $v0, $v1, $v0
lb      $v0, 0($v0)

取出相应字节的字符,然后进行下面一系列操作。

sll     $v0, 2
sll     $a0, $v0, 24
sra     $a0, 24
lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)
nop
addu    $v0, $v1, $v0
lb      $v0, 0($v0)

首先左移两位,再左移24位,再进行右移24位(绝对不是简简单单的左移两位。。。别搞错。。
然后取出位数放在v0中,取出数组首地址放在v1中,紧接着也取出相应位数字节的字符放在v0里面。
总结:也就是取出一字节字符的低6位放在a0寄存器

sra     $v0, 6
sll     $v1, $v0, 24
sra     $v1, 24
lw      $v0, 0x28+var_10($fp)
lw      $a1, 0x28+arg_0($fp)
nop

右移6位,再左移24位,再进行右移24位(绝对不是简简单单的右移6位。。。别搞错。。
取出位数放在v0中,取出数组首地址放在v1中。
总结:也就是取出一字节字符的高2位放在v1寄存器

addu    $v0, $a1, $v0
or      $v1, $a0, $v1
sll     $v1, 24
sra     $v1, 24
sb      $v1, 0($v0)

第一行,把相应字节的字符地址取出放在v0寄存器中,
然后把v1寄存器(取出一字节字符的高2位)和a0寄存器(取出一字节字符的低6位)进行或运算放在v1寄存器中,
紧接着进行左移24,右移24,保留低八位(即一字节),然后把运算结果塞入上面取出的地址处的内存单元
即一字节循环左移2位

奇数位

lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)
nop
addu    $v0, $v1, $v0
lb      $v0, 0($v0)
nop
sra     $v0, 2
sll     $a0, $v0, 24
sra     $a0, 24
lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)
nop
addu    $v0, $v1, $v0
lb      $v0, 0($v0)
nop
sll     $v0, 6
sll     $v1, $v0, 24
sra     $v1, 24
lw      $v0, 0x28+var_10($fp)
lw      $a1, 0x28+arg_0($fp)
nop
addu    $v0, $a1, $v0
or      $v1, $a0, $v1
sll     $v1, 24
sra     $v1, 24
sb      $v1, 0($v0)
b       loc_400900
nop

同样的方法,来分析奇数位字符

lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)

第一行把位数取出来,第二行把参数取出来,因为我们前面传参的时候传的时字符串的地址。
所以v0里面是位数,v1里面是字符串首地址。

addu    $v0, $v1, $v0
lb      $v0, 0($v0)

取出相应字节的字符,然后进行下面一系列操作。

sra    $v0, 2
sll     $a0, $v0, 24
sra     $a0, 24
lw      $v0, 0x28+var_10($fp)
lw      $v1, 0x28+arg_0($fp)
nop
addu    $v0, $v1, $v0
lb      $v0, 0($v0)

首先右移两位,再左移24位,再进行右移24位(绝对不是简简单单的右移两位。。。别搞错。。
然后取出位数放在v0中,取出数组首地址放在v1中,紧接着也取出相应位数字节的字符放在v0里面。
总结:也就是取出一字节字符的高6位放在a0寄存器

sll     $v0, 6
sll     $v1, $v0, 24
sra     $v1, 24
lw      $v0, 0x28+var_10($fp)
lw      $a1, 0x28+arg_0($fp)
nop

左移6位,再左移24位,再进行右移24位(绝对不是简简单单的左移6位。。。别搞错。。
取出位数放在v0中,取出数组首地址放在v1中。
总结:也就是取出一字节字符的低2位放在v1寄存器

addu    $v0, $a1, $v0
or      $v1, $a0, $v1
sll     $v1, 24
sra     $v1, 24
sb      $v1, 0($v0)

第一行,把相应字节的字符地址取出放在v0寄存器中,
然后把v1寄存器(取出一字节字符的高6位)和a0寄存器(取出一字节字符的低2位)进行或运算放在v1寄存器中,
紧接着进行左移24,右移24,保留低八位(即一字节),然后把运算结果塞入上面取出的地址处的内存单元
即一字节循环右移2位

尾声

loc_400900:
lw      $v0, 0x28+var_10($fp)
nop
addiu   $v0, 1
sw      $v0, 0x28+var_10($fp)

取出位数,进行加1操作

loc_400910:              # s
lw      $a0, 0x28+arg_0($fp)
jal     strlen
nop
move    $v1, $v0
lw      $v0, 0x28+var_10($fp)
nop
sltu    $v0, $v1
bnez    $v0, loc_400814
nop

当操作到最后一个时

sltu    $v0, $v1
bnez    $v0, loc_400814


BENZ R1,NAME;//R1!=0,程序跳转,以NAME为偏移地址,当移动到最后一个字符的下一个时,v0=v1相等。条件跳转不成立,紧接着进行一系列比较

lw      $v0, 0x28+arg_0($fp)
nop
addiu   $v1, $v0, 5
lw      $v0, off_410D04
li      $a2, 0x1B        # n
move    $a1, $v0         # s2
move    $a0, $v1         # s1
jal     strncmp
nop
bnez    $v0, loc_40097C
nop

off_410D04地址处

 52 FD 16 A4 89 BD 92 80  13 41 54 A0 8D 45 18 81  DE FC 95 F0 16 79 1A 15  5B 751F

比较结束后,返回值为1,则不跳,即

lui     $v0, 0x40
addiu   $a0, $v0, (aRight - 0x400000)  # "Right!"
jal     puts
nop
b       loc_40098C
nop

成功喽!!!!!!!!

GAMEOVER

part1=b'Q|j{g'
part2='52 fd 16 a4 89 bd 92 80 13 41 54 a0 8d 45 18 81 de fc 95 f0 16 79 1a 15 5b 75 1f'
part2=list(bytes.fromhex(part2))
for i in range(5,len(part2)+5):t = part2[i-5]if i&1==0:   #偶数时&1 为0part2[i-5]=(t&0x3)<<6|(t&0xfc)>>2   #低2位左移6位,高6位右移2位  相当于循环右移2位else:part2[i-5]=(t&0x3f)<<2|(t&0xc0)>>6  #低6位左移2位,高2位右移6位  相当于循环左移2位temp=list(part1)+part2
flag=''
for i in range(len(temp)):flag+=chr(temp[i]^0x20 -i)
print(flag)

qctf{ReA11y_4_B@89_mlp5_4_XmAn_}

babymips(下) 寒假逆向生涯(14/100)相关推荐

  1. babymips(上) 寒假逆向生涯(14/100)

    babymips 这题呢,看名字就知道,不出所料,还是mips指令,挺简单的,懒得找插件,直接分析吧,锻炼锻炼自己 开战 lui $v0, 0x40 addiu $a0, $v0, (aGiveMeY ...

  2. notsequence 寒假逆向生涯(9/100)

    notsequence 这题目,挺简单的,首先无壳,直接拖进ida,然后查看了一下伪代码 轻易发现只需要满足三点就行 sub_80486CD((int)&unk_8049BE0) (unsig ...

  3. secret-galaxy-300 Replace(印象深刻) 寒假逆向生涯(8/100)

    secret-galaxy-300 脑洞题,直接没说法,就以后别碰这种脑洞题就行,,,,没任何帮助 显示界面 OD打开后,显示这个鬼东西.然后就没了. ida静态分析 看到上方输出框有字符串,所以我们 ...

  4. easy_Maze 梅津美治郎 寒假逆向生涯(16/100)

    easy_Maze 这个题简单,迷宫题目,需要动调,或者不用动调也行,可以自己算出地图,我用的是动调. 生成地图的两个函数 只需要动调到这两个函数的下一步后,找到储存矩阵的空间的地址, 把这个地址转到 ...

  5. easyre-153 testre寒假逆向生涯(13/100)

    easyre-153 简单题目,流程走起,首先查壳, 脱壳 upx壳,利用工具把它脱掉 ida静态分析 int __cdecl main(int argc, const char **argv, co ...

  6. re-for-50-plz-50 寒假逆向生涯(6/100)

    re-for-50-plz-50 这题目属实没法看伪代码(当然,可以下载插件进行一系列帮助),在这里呢,我直接读mips的指令集,因为涉及到的指令挺简单的 MIPS32指令集对照 全部指令 .text ...

  7. EasyRE 寒假逆向生涯(5/100)

    EasyRE 声明 挺简单的一道题目,流程不必注意太多,直接上核心伪代码 首先注意一点 v2 = (char *)&v8 + 7;这行代码属于编译出错,我们需要直接 查看它的汇编代码, 这行代 ...

  8. hackme Guess-the-Number 寒假逆向生涯(4/100)

    hackme 声明 简单题目,没必要查壳,动调. 话不多说,上核心伪代码 大致思路: 一个for循环,外加一个while循环 while循环是找出相应条件下v12的值 for循环作用: 1.制造whi ...

  9. IgniteMe debug 寒假逆向生涯(2/100)

    IgniteMe 声明 这是道超级简单的题目,就不重复啰嗦了,找到需要加密的关键代码后,直接一步到位. memset(&v4, 0xCCu, 0xF4u);if ( strlen(a1) &g ...

最新文章

  1. 关于最长公共子序列的执行过程
  2. OpenCASCADE:Modeling Data之形状的属性
  3. InsightFace及其mxnet、tensorflow代码实现
  4. ZooKeeper命令、命令行工具及简单操作
  5. php是否支持64位,phpstudy默认不支持64位php的解决方法
  6. 背景图宽度自适应及背景图合并的CSS思想
  7. FFmpeg学习(5)——视频加水印
  8. 企业办理CMMI认证是怎么收费的?
  9. 通过eclipse对apk加密混淆的方法
  10. 电梯plc的io分配_用PLC构成液体混合控制系统IO分配及梯形图编程
  11. 加拿大前十大学计算机硕士学费,2018年加拿大各大学硕士学费一览表!
  12. xcode8插件管理工具
  13. 不谋一时不足以谋一域_“不谋万世者,不足谋一时。不谋全局者,不足谋一隅”出自哪里?是什么意思?...
  14. 项目上传图片报:Can't create output stream!
  15. 计算机休眠是意思,电脑休眠是什么意思(电脑休眠和睡眠的区别)
  16. js中的JSON对象转换,过滤特殊字符数据
  17. 微信中H5+java+vue获取微信定位等JS-SDK
  18. dnf红眼补丁在哪下载_dnf红眼变红补丁下载
  19. pc端,移动端,客户端的区别
  20. windows git bash 设置多个php版本和composer版本

热门文章

  1. python优先级排序_Python实现优先级队列结构的方法详解
  2. Computer:路由器、交换机、猫Modem的简介、区别之详细攻略
  3. 成功解决numpy.linalg.LinAlgError: singular matrix
  4. Paper:《Graph Neural Networks: A Review of Methods and Applications》翻译与解读
  5. 成功解决ValueError: Cannot feed value of shape (1, 10, 4) for Tensor Placeholder:0 , which has shape
  6. DL:听着歌曲《成都》三分钟看遍主流的深度学习的神经网络的发展框架(1950~2018)
  7. Crawler之Scrapy:Scrapy简介、安装、使用方法之详细攻略
  8. 在Linux上如何安装Oracle数据库
  9. Docker 三架马车
  10. 莫队(不带修改)模板