攻防世界逆向高手题之Windows_Reverse1

99 篇文章 33 订阅

攻防世界逆向高手题之Windows_Reverse1

继续开启全栈梦想之逆向之旅~
这题是攻防世界逆向高手题的Windows_Reverse1
在这里插入图片描述

下载附件,照例扔入exeinfope中查看信息:
在这里插入图片描述

UPX壳,32位windows中,扔入我的kali中先用命令upx -d 文件名 脱壳先:
在这里插入图片描述

双击运行不了,查看不了起始信息,看了资料说:

UPX的壳,手动脱壳或者脱壳机脱壳,但发现脱完壳的程序在win7下打不开,即使是显示没壳(这里后来查到win7包括以上版本开启了ASLR(地址随机化),winxp就没有,如果程序采用绝对地址,在win7和win10上就运行不了),直接IDA启动,IDA里不爆红就没事。

不管了,IDA分析伪代码:
在这里插入图片描述

.
.
代码一目了然,神奇的是红框框起来的地方。这里积累第一个经验:出入的是input_flag(v6改名而来),结果比较的是v4,一开始我以为是IDA出了错误,后来才发现题目考的就是我以前一直说得地址偏移间接操作。v4存入了寄存器中,用的是寄存器操作。
.
.

input_flag点进去-00000404 var_404 db ?
v4点进去-00000804 var_804 db ?
.
.
这里积累第二个经验:查看反汇编代码,前面有sub esp, 804h,所以esp+804h处可以说是基址EBP的地方,这里的[esp+82Ch+input_flag]和[esp+830h+v4]只是在esp+804h的EBP基础上加上中间代码的指令字节长度而已,本质就是取input_flag和v4参数。
在这里插入图片描述

这里Input_flag和v4分别给了eax和ecx,我们查看sub_401000函数的反汇编代码和函数图都可以发现ECX被使用了:

在这里插入图片描述

在这里插入图片描述
.
.
.
input_flag和v4的问题解决了,下面我们分析逻辑代码:

unsigned int __cdecl sub_401000(const char *input_flag)
{
  _BYTE *v1; // ecx即v4
  unsigned int v2; // edi
  unsigned int result; // eax
  int v4; // ebx

  v2 = 0;
  result = strlen(input_flag);
  if ( result )
  {
    v4 = input_flag - v1;                //这里积累第三个经验:地址减地址取差值。这里v4是Input_flag和v1(主函数v4)的地址的差值
    do
    {
      *v1 = byte_402FF8[(char)v1[v4]];	//这里积累第四个经验:这里V1作为地址和v4作为地址差值执行的是v1+v4的操作,因为数组a[b]本质就是在数组头地址a加上偏移量b来遍历数组的,所以这里是一种遍历input_flag的新操作,至于最外面的byte_402FF8[]数组框,应该这样理解,v1[v4]逐个取input_flag的单个字符,这个字符的ascii码作为偏移继续在byte_402FF8[]数组中寻址。(PS:这不是Python中list.index()函数可以用字符查找对应索引!)
      ++v2;
      ++v1;
      result = strlen(input_flag);
    }
    while ( v2 < result );
  }
  return result;
}

.
.
也附上别人博客的解释:

1:a1是通过压栈的方式传递的参数; v1是通过寄存器保存地址的方式传递的参数

2:最令人迷惑的便是v1[v4]这个地方. v1是一个地址, v4是a1和v1两个地址间的差值. 地址的差值是怎么成为一个数组的索引的呢 ?
3:这里卡了我好长时间, 之后我突然意识到, v1[v4]和v1+v4是等价的, 而在循环刚开始的时候v1+v4等于a1, 随着v1的递增,v1[v4]也会遍历a1数组中的各个元素的地址

4:而地址又怎么能作为数组的索引呢? 这里就是 IDA 背锅了, 换言之, 做题还是不能太依赖于反编译后的伪代码. 查看了反汇编代码后, 发现其实是将a1字符串中的字符本身作为byte_402FF8的索引, 取值后放入v1数组中

———————————————— 版权声明:本文为CSDN博主「Code Segment」的原创文章,遵循CC 4.0
BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43547885/article/details/104412656

.
.
.
双击跟踪byte_402FF8[]数组:
在这里插入图片描述

在这里插入图片描述

.
.
可以看到前面乱码?,后面倒是有字符串,数组地址偏移从0x00402FF8~0x00403078。
这里积累第5个经验:ASCII编码表里的可视字符就得是32往后了, 所以, byte_402FF8里凡是位于32以前的数统统都是迷惑项. 不会被索引到的,而这里0x00402FF8~0x00403017刚好是32个字符。那么后面有字符串就可以解释通了,它们是连在一起的。
.
.
.
数组有了,逻辑有了,逆向逻辑很简单,先用IDA脚本打印0x00402FF8~0x00403078数组处的地址内容先:

addr=0x00402FF8
arr=[]
for i in range(0x00403078-0x00402FF8):    #数组的个数
    arr.append(Byte(addr+i))
print(arr)
print(len(arr))

在这里插入图片描述

.
.
.
复制数组内容写逆向脚本:

key1=[255, 255, 255, 255, 255, 255, 255, 255, 78, 230, 64, 187, 177, 25, 191, 68, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 1, 0, 0, 0, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 0]
key2="DDCTF{reverseME}"
flag=""
for i in key2:
	flag+=chr(key1[ord(i)])
print("flag{"+flag+"}")

.
.
结果:
在这里插入图片描述
.
.
.
总结:

1:
这里积累第一个经验:出入的是input_flag(v6改名而来),结果比较的是v4,一开始我以为是IDA出了错误,后来才发现题目考的就是我以前一直说得地址偏移间接操作。v4存入了寄存器中,用的是寄存器操作。

2:
这里积累第二个经验:查看反汇编代码,前面有sub esp,
804h,所以esp+804h处可以说是基址EBP的地方,这里的[esp+82Ch+input_flag]和[esp+830h+v4]只是在esp+804h的EBP基础上加上中间代码的指令字节长度而已,本质就是取input_flag和v4参数。

3:
v4 = input_flag - v1;
//这里积累第三个经验:地址减地址取差值。这里v4是Input_flag和v1(主函数v4)的地址的差值

4:
这里积累第四个经验:这里V1作为地址和v4作为地址差值执行的是v1+v4的操作,因为数组a[b]本质就是在数组头地址a加上偏移量b来遍历数组的,所以这里是一种遍历input_flag的新操作,至于最外面的byte_402FF8[]数组框,应该这样理解,v1[v4]逐个取input_flag的单个字符,这个字符的ascii码作为偏移继续在byte_402FF8[]数组中寻址。(PS:这不是Python中list.index()函数可以用字符查找对应索引!)

5:
这里积累第5个经验:ASCII编码表里的可视字符就得是32往后了, 所以,
byte_402FF8里凡是位于32以前的数统统都是迷惑项.
不会被索引到的,而这里0x00402FF8~0x00403017刚好是32个字符。那么后面有字符串就可以解释通了,它们是连在一起的。

解毕!敬礼!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐一 · 林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值