babymips(下) 寒假逆向生涯(14/100)
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, $v0v0赋值给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"这五个的原因吧)即选择跳
把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里面是字符串首地址。
取出相应字节的字符,然后进行下面一系列操作。
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寄存器
右移6位,再左移24位,再进行右移24位(绝对不是简简单单的右移6位。。。别搞错。。)
取出位数放在v0中,取出数组首地址放在v1中。
总结:也就是取出一字节字符的高2位放在v1寄存器
第一行,把相应字节的字符地址取出放在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里面是字符串首地址。
取出相应字节的字符,然后进行下面一系列操作。
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寄存器
左移6位,再左移24位,再进行右移24位(绝对不是简简单单的左移6位。。。别搞错。。)
取出位数放在v0中,取出数组首地址放在v1中。
总结:也就是取出一字节字符的低2位放在v1寄存器
第一行,把相应字节的字符地址取出放在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相等。条件跳转不成立,紧接着进行一系列比较
off_410D04地址处
比较结束后,返回值为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)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: babymips(上) 寒假逆向生涯(1
- 下一篇: easy_Maze 梅津美治郎