没事刷刷 逆向题 pwn题 也没事看看~~~~~
第一题
拖入ida 看一下
注释的就是答案~~~~
第二题
这个题 就直接 看就行 下面就是脚本
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
int s[9]= {0x5B,0x13,0x49,0x77,0x13,0x5E,0x7D,0x13};
int main()
{
int ss[5]={16,32,48};
int v3=0;
for ( int i = 0; v3 <8; ++i )
{
if ( i >= 3 )
i = 0;
printf("%c",s[v3++]^ss[i]);
}
return 0;
}
第三题
这个题 用esp 就能找到oep 那么
上我写的 od 脚本把
VAR addr
STO
MOV addr,esp
bphws addr,"w"
RUN
bphwc addr
findop eip,#E9??#
go $RESULT
STO
CMT eip,"这里是入口"
MSG "皮皮虾制作"
ret
直接到 oep
第四题
不得不说 我以前还是做过vb程序的题的
先用vb程序反编译一下
然后 因为以前看一个视频写的一个外挂就是用vb写的 所以也是了解过一些的
然后
其实 从函数名里其实就能看到 函数的作用 这里就是 停止
这里是 上面函数的调用处 ,,, 然后 用od 断点
然后运行几次 发现哪里和 能运行不一样就jmp掉 然后就可以 播放了
最后的答案
注意第二个是 大写I 我还以为是小写l
这道题 真的恶心到我了 这道题难不是难 主要头有点晕 一直忘了 eax这个东西 。。。
这个 题需要一些底层知识 如果底层不是很了解的话 确实不太好做这个题
先说一下 这个题的策略 我一开始没有直接调试 先随便输入几个数字 程序就直接退出了 而且看着这个题 不像是程序自动退出的 反而像出了什么错误 然后 我们用 ida f 5看的 话 会有一些不太清楚 我们直接看汇编代码
这一行我只看懂了 add dword_4084D0, 601605C7h。。。
然后我们随便输入数字 调试一下
od 里面的指令变来变去的 看的我头皮发麻 然后 返回的时候看一下数字
发现 我们 经过调试 我发现了 几个 规律
假如 eax能装下的最大值 没有输入的值大的话 那么最后的值是ds:[004084D0]=601605CB
假如 不是的话 那么 就是 601605CB +我们输入的值 &FFFFFFFF 这个601605CB 来的 我大概分析的应该不错 那就是 inc 循环了 4次 然后 add 601605C7 那么加起来 就是那个数字
那么这里又要问了 为什么程序会崩 看一下下面的指令
程序找不到这个地址 所以就崩了。。。 而0x90的意思就是 nop 我们搞破解的时候 经常把 jmp 搞成nop 然后完成破解
那么如果我们控制输入 把一个跳转 给nop掉 是不是程序就出来了
401071 就是程序的返回地址 我们控制输入把他的地址给搞定就成 符合条件的数字就一个 2687109798
不得不说 这个网站惊艳到我了 这个题 我看了好久没有看出来是什么意思
看的出来加载了一个 资源 但是资源很多 我并不知道资源是在哪呀。。。 不过画笔这个东西还是接触过
在C++ 课程设计实现了一个 局域网玩的五子棋 棋盘就是通过 画笔画的 但是他这个我确实get不到点
v11就是我们寻找到的资源 然后 与我们的画布的 资源比较 然后如果相同点是 大于
这里是按照字节比较的应该 然后 我用 一个工具把这东西提取了出来
但是接下来我就不知道怎么处理了 。。。。文件格式处理这方面我确实很差。。。。 然后搜了一下大佬的博客 才搞定
https://blog.csdn.net/qq_33438733/article/details/82108961 这里用了 python库
由于python2 好像要停止更新了 所以我这里用的py3写的 其实也差不多
import string
from PIL import Image,ImageFont,ImageDraw
width = 200
height = 150
if __name__ =="__main__":
fp = open('Wx', 'rb')
data = fp.read()
pipixia = Image.frombytes('RGB', (width, height), data)
pipixia = pipixia.transpose(Image.FLIP_TOP_BOTTOM)
pipixia.show()
这是效果
。。。。 真的很好玩的题
Position 这个题比较可惜 本来我一开始感觉 这个题 有点难度 于是我 选择了 硬核分析
然后。。。。。 慢慢看的话 还是很好懂的 就是 数字拆分 然后加上 在组合 比较简单 然后我发现了
这里竟然代表长度 后来想了想 应该是 mfc的 字符串的存储结构 代码 应该是用的宏 (类似 getlength) 然后编译器 给优化了吧 这里感觉很好玩 然后这个题 范围 已经给限定好了 而且就4个字符 暴力就可以解决的问题。。。 下面是脚本
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
int main()
{
int password[11]={7,6,8,7,6,0,7,7,7,7,6};
int snum[10];
for(int i='a'; i<='z'; i++)
{
for(int j='a'; j<='z'; j++)
{
snum[0] = (i & 1) + 5;
snum[1] = ((i >> 4) & 1) + 5;
snum[2] = ((i >> 1) & 1) + 5;
snum[3] = ((i >> 2) & 1) + 5;
snum[4] = ((i >> 3) & 1) + 5;
snum[5] = (j & 1) + 1;
snum[6]= ((j >> 4) & 1) + 1;
snum[7] = ((j >> 1) & 1) + 1;
snum[8] = ((j >> 2) & 1) + 1;
snum[9] = ((j >> 3) & 1) + 1;
if(!((snum[0]+snum[8]==password[0])&&
(snum[4]+snum[9]==password[1])&&
(snum[2]+snum[6]==password[2])&&
(snum[3]+snum[5]==password[3])&&
(snum[1]+snum[7]==password[4])))
{
continue;
}
for(int k='a'; k<='z'; k++)
{
for(int l='a'; l<='z'; l++)
{
snum[0] = (k & 1) + 5;
snum[1] = ((k >> 4) & 1) + 5;
snum[2] = ((k >> 1) & 1) + 5;
snum[3] = ((k >> 2) & 1) + 5;
snum[4] = ((k >> 3) & 1) + 5;
snum[5] = (l & 1) + 1;
snum[6]= ((l >> 4) & 1) + 1;
snum[7] = ((l >> 1) & 1) + 1;
snum[8] = ((l >> 2) & 1) + 1;
snum[9] = ((l >> 3) & 1) + 1;
if(((snum[0]+snum[8]==password[6])&&
(snum[4]+snum[9]==password[7])&&
(snum[2]+snum[6]==password[8])&&
(snum[3]+snum[5]==password[9])&&
(snum[1]+snum[7]==password[10])))
{
if(i!=j&&i!=l&&i!=k&&j!=l&&j!=k&&l!=k&&l=='p')
printf("%c%c%c%c\n",i,j,k,l);
}
}
}
}
}
return 0;
}
结果是
第一个是正确答案
这个题 不知道当时为何我一开始没有运行成功 感觉好奇怪 。。。
然后后来又运行成了 2333
这个题 分析的时候 挺茫然的 然后想了一下 看哪里有运行程序成功的地方 应该就是flag
在这里 找到了 gameover 然后我们向下分析
这里 的 409194 还有 40f8b4 应该是 怪物的地址?? 每次 的 加的大小是怪物的 结构的大小 我猜想 应该是这样。。
然后 我们 看一下 byte_407028 的 内容
还有很多并没有 不可见字符。。
这里 发现 还有地方调用了 他 而且是 异或 突然感觉这里正确的点。
这里有个异或点 。。。。。 但是这里面并没有值
让程序跑一下试试
然后发现好像可以了
那么我们呢 就用python脚本写一下
import sys
from idautils import *
from idc import *
import idaapi
if __name__ =="__main__":
list1=[]
list2=[]
for i in range(50):
sys.stdout.write(chr(Byte(0x179184 + i*132*4)^(Byte(0x177028 + i))))
万万没有想到的是 我还会被野怪给搞死了
233333
下面是效果
Ransomware 这个题 upx脱完壳的时候
发现了 中间有很多花指令 但是一开始 并不是 花指令
#!/usr/bin/env python
# -*- coding:utf-
import sys
from idautils import *
from idc import *
import idaapi
if __name__ =="__main__":
start=0x004135E0
end=0x004135E8
end1=0x0044A774
start1=0x44A76C
n=0
while(start+n!=end+1):
PatchByte(start1+n,Byte(start+n))
PatchByte(start+n,0x90)
n+=1
我们用python 脚本直接 给 nop 掉 然后直接 用改ida 函数的大小 把我们的其实地址 改成 0x44a76c 然后就 成功f5
由于我这个题 到最后也没有分析出结果 看了一下 大佬的博客 下面是博客链接
https://blog.csdn.net/whklhhhh/article/details/78137138
这里 奇妙的第一点是
data = open(‘run.exe’,’rb’).read()
data = data.replace(‘\x60\x61\x90\x50\x58\x53\x5b’,’\x90\x90\x90\x90\x90\x90\x90’)
open(‘run_dejunk.exe’,’wb’).write(data)
这里可以直接 把 401000给nop掉 其实 在ida python里面应该也是可行的
然后 第二点是。。。。 这个题的key 到底怎么求啊
就看到了 这两行代码有用 可是 他也没有 比较正确答案。。。
后来看那个博客 知道要用 资源文件 看
这里有个循环 打印出来 看看 有没有有意义的字符串。。
然后发现了 letsplaychess 。。 虽然我并不知道为什么这个搞
接下来 就很好搞了 我们只需要把函数逆向来就行了 这里直接粘上上面的博客代码
key = "letsplaychess"
f = open("file", "rb")
data = f.read()
exe = []
for i in range(len(data)):
exe.append(((~data[i] ^ ord(key[i%len(key)])) % 256))
f.close()
f = open("file_de.exe", "wb")
f.write(bytes(exe))
f.close()
这个程序就非常明显了 直接打印出来就好
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
int main()
{
printf("%c",'x'^0x34u);
printf("1");
printf("%c",'|'^0x32u);
printf("%c",0xDDu^0x88u);
printf("X");
return 0;
}