本人是个web,迫于生计,也前来学习一点逆向的知识,打算以攻防世界的ctf题来练手,以后会同步更攻防世界的逆向和mobile方向(萌新入门,不对的地方还请师傅多多指教),至于web,另外一个栏目已经有差不多的总结了,也在更新。
先打开查看运行情况
然后我们放入exeinfope.exe中查看其可运行版本位,可看出为32位,以下有两种解法,ida和od。
之后我们用ida32位的程序打开它,看到main这里之后,进行反汇编按F5,下下图为效果图。
根据审计顺序做了标记,1.可看到v9这输入值;2,3.strcmp函数将v5和v9进行比较,符合就进入下一步给出正确flag的提示“aflag_0”;4.我们向上寻找v5,发现可以看到开头的_mm_storeu_si128(),对其进行分析发现它将xmmword_413E34的值赋值给v5,所以我们跟进到xmmword_413E34中。
这里是十六进制,按下r将其转换为字符串
假设一个十六进制数0x12345678
大端的存储方式是:12,34,56,78,然后读取的时候也是从前往后读
小端的存储方式是:78,56,34,12,然后读取的时候是从后往前读取
最后的flag:DUTCTF{We1c0met0DUTCTF}
首先,最简单的直接搜索类似于字符串“flag”的方法就不说了。
打开OD后,一路来到如下图,这里最好还是要结合ida和汇编代码进行分析
我们在右侧程序输入后回车,就可以看到右面寄存器有了flag值,在这里cmp即相当于strcmp函数,对应的就可以在寄存器读到对应的比较值--flag
首先打开看看长啥样,之后用工具得出32位,下面我们分别用ida和od进行解题。
鉴于28行前代码无关紧要就不放在这里占空间了,同时说下如果IDA不能正确的获得自定义函数的名字,那么IDA会用sub__加上自定义函数的起始地址来定义函数的名字
35行的v2被赋为输入的值,之后if使v2属于[0,8]
在这里我们可以得出使byte_532E28每一位都是1,就会进入sub_457AB4(),我们猜测这可能就是出flag的地方。
继续跟进sub_457AB4()
此处省略部分...
基本可以推测出后面的为print函数,那么我们只要算出for循环里的就可以拿到flag了,上脚本
a = [123,32,......,126,0]
b = [18,64,......,16,0]
c = 0
flag = ''
while (c<56):
a[c] ^= b[c]
a[c] ^= 0x13
flag = flag + chr(a[c])
c = c + 1
print(flag)
首先找到可能为最后flag的地址,跟进
图标为1的就是跟进的地址了,我们看标2的地方就是开始我们这个函数的地址,跟着红箭头一路向上找就可以找到跳转的地址
记住这个地址:E37AB4,我们再去寻找失败的地方
继续跟进
到了这,我们只需要覆盖掉就可以直接到达出flag的函数,输入jmp 0xE37AB4
一堆定义,没有用
题比较简单,就不细说了,都放在注释了
根据题目指点,编译后直接对源代码进行分析,下面的注释就是解题过程
#include
#include
int main(int argc, char *argv[]) {
if (argc != 4) { //判断输入参数,这里除程序名还需要写3个
printf("what?\n");
exit(1);
}
unsigned int first = atoi(argv[1]); //第一处输入十进制51966
if (first != 0xcafe) {
printf("you are wrong, sorry.\n");
exit(2);
}
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) { //第二处逻辑判断,前后两个条件都不能符合
printf("ha, you won't get it!\n");
exit(3);
}
if (strcmp("h4cky0u", argv[3])) { //第三处比较判断,直接输入h4cky0u
printf("so close, dude!\n");
exit(4);
}
printf("Brr wrrr grr\n");
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}
第二处的脚本
for a range (0,100):
if (a % 5 != 3 and a % 17 == 8):
print (a)
得出a可为25,然后得到flag
我醉了。。。小朋友你是否有很多问号
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
size_t v3; // rsi
int i; // [rsp+3Ch] [rbp-54h]
char s[36]; // [rsp+40h] [rbp-50h]
int v6; // [rsp+64h] [rbp-2Ch]
__int64 v7; // [rsp+68h] [rbp-28h]
char v8[8]; // [rsp+70h] [rbp-20h]
int v9; // [rsp+8Ch] [rbp-4h]
v9 = 0;
strcpy(v8, ":\"AL_RT^L*.?+6/46");
v7 = 28537194573619560LL;
v6 = 7;
printf("Welcome to the RC3 secure password guesser.\n", a2, a3);
printf("To continue, you must enter the correct password.\n");
printf("Enter your guess: ");
__isoc99_scanf("%32s", s);
v3 = strlen(s);
if ( v3 < strlen(v8) )
sub_4007C0();
for ( i = 0; i < strlen(s); ++i )
{
if ( i >= strlen(v8) )
sub_4007C0();
if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) ) //看到sub_4007c0()为输出错误flag,所以只要满足两边相等即可
sub_4007C0();
}
sub_4007F0();
}
很简单的一段逻辑,不对以上代码进行细致分析了,我们注意到的是在第二个if判断里,有一个对i大小的限制,这里duck不必,直接写脚本实现第三个if两边相等即可得到flag
int main(){
long long v7 = 28537194573619560;
char *a = (char *)&V7;
char V8[] = ":\"AL_RT^L*.?+6/46";
for(int i=0;V8[i]!=0;i++){
V8[i]=V8[i]^a[i%7];
}
cout<
是个pyc文件,反编译一下,网址:https://tool.lu/pyc/ ,下面是反编译的源码
import base64
def encode(message): //加密过程,最后来个base64...
s = ''
for i in message:
x = ord(i) ^ 32
x = x + 16
s += chr(x)
return base64.b64encode(s)
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
print 'correct'
else:
print 'wrong'
解密脚本:
import base64
flag = ""
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
b64_flag = base64.b64decode(correct)
for i in b64_flag:
x = (i-16) ^ 32
flag += chr(x)
print(flag)
本来是想写完新手区的WP,但是时间原因吧,后面几个题感觉也没有什么写的必要了,之后在本人博客更新免杀等,日后再见