攻防世界逆向入门题之getit
继续开启全栈梦想之逆向之旅~
这题是攻防世界逆向入门题的getit

讯享网
下载附件,照例扔入exeinfope中查看消息:


64位ELF文件,然后扔入IDA查看伪代码信息:

让我们来分析这段C代码含义:首先我看到的是strcpy(filename, “/tmp/flag.txt”);
stream = fopen(filename, “w”);
因为这里有flag字眼,所以我一下就看到了它,这里说写入了/tmp/flag.txt,也因为是tmp文件,所以不是管理员也可以写入,后面显眼的
fclose(stream);
remove(filename);
也说明了一运行完程序就删除文件,所以我们没法在运行完程序后找到该文件
现在分析中间的循环写入语句:
for ( i = 0; i < strlen(&t); ++i ) //我是认为&t是flag的长度 {
fseek(stream, p[i], 0); //定位到开头偏移p[i]位置处, fputc(*(&t + p[i]), stream); //在上一句的定位处写入&t起始字符串的p[i]偏移的单个字节 fseek(stream, 0LL, 0); //重新定位到0且没有偏移 fprintf(stream, "%s\n", u); //写入完整字符u,双击跟踪u发现是*,就是一个覆盖干扰 }
讯享网
这里的p[i]双击跟踪长这个样子:(p[i]鼠标长时间停留显示int[43]类型):

hex图比较直观:
可以看到p[i]数组存放的是无序的整数,也就是说每次在/tmp/flag.txt文件中写入的flag是不按顺序写的,且每次只出现一个字符,需要自己排序。
开头的循环判断中的&t在前面出现过,长这个样子:

我当时看着逼格挺高的,记得看不懂就没鸟了,后来发现前面的循环才是生成的flag代码,后面只是将flag分成单个单个字符写进去而已。
所以让我们分析一下前面代码:
讯享网 v9 = __readfsqword(40u); //这里我也不清楚,是windows的API函数,从偏移量的指定位置读取内存相对 FS 段开头 LODWORD(v5) = 0; //这里把__in64的v5(longlong型)转地址类型为32为DWORD,即取底32位为0 while ( (signed int)v5 < strlen(s) ) //这里signed int是有符号整形,s双击跟踪是c61b68366edeb7bdce3cb7498这样的无序字符串 {
if ( v5 & 1 ) //这里是v5的1位和1进行与操作,因为后面有LODWORD(v5) = v5 + 1,所以v3在这里会1、-1这样反复横条strlen(s)次 v3 = 1; else v3 = -1; *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3; //这里是赋值,因为v5一开始是0,所以从&t+10开始赋值,&t双击跟踪是SharifCTF{
????????????????????????????????},第10位刚好是第一个?,赋值是从s[0]开始-1,s[1]+1,s[2]-1这样赋值,分别对应不断递增的v5和反复横跳的v3,所以这里也可以手动计算第一个?是b,第二个?是7这样。 LODWORD(v5) = v5 + 1; //v5底32位加1,其实就是v5加1 }
第二种动态截停,截止flag生成后的位置,查看寄存器即可。
第三种静态计算,仿写c语言脚本或python脚本安装一样的算法生成flag。
第四种动态截停,在IDA远程调试中截停在remove(filename);最后这里,或者return 0;也行,然后在IDA中写python脚本命令输出&t地址的字符串即可。
第五个动态截停,在linux中用GDB或IDA远程调试断点断在fprintf(stream, “%s\n”, u); 这里,然后每次记录写入的一个flag字符。

第一种就不说了,自己计算即可。
第二种:GDB动态调试,首先我们知道了下面strlen(&t)的t是flag程序运行后生成的flag,那我们把鼠标放在那一行上看一下下面的反汇编行数,如下所示是,那么我们在反汇编窗口跟上。

可以看到反汇编中行的确是_strlen函数,而它上面就是把&t移入了edi,所以在GDB中我们断点,然后查看edi寄存器即可。
所需命令:
b *0x r
我这里用的是hyperpwn插件:

可以看到flag就在RDI寄存器里。
讯享网key1="c61b68366edeb7bdce3cb7498" v5=0 flag="" while v5 < len(key1): if v5 & 1: v3=1 else: v3=-1 flag+=chr(ord(key1[v5])+v3) v5+=1 print(flag)

C语言代码:(复制别人的)
#include <stdio.h> #include <stdlib.h> #include <Windows.h> #pragma warning(disable:4996) int main(void) {
char v3; __int64 v5; char s[] = "c61b68366edeb7bdce3cb7498"; char t[] = "SharifCTF{????????????????????????????????}"; v5 = 0; while (v5 < strlen(s)) {
if (v5 & 1) v3 = 1; else v3 = -1; *(t + v5 + 10) = s[v5] + v3; v5++; } printf("%s", t); system("PAUSE"); return 0; }
第四种在IDA处动态截停:
直接双击t看到?已经被替换成flag了,这里是断点在return
或者在IDA下面输入框下输入get_bytes(0x6010E0,50)也一样能打印出对应地址的数组
第五种:嗯~第五种就不演示了,大致像这个样子吧,不过他这个是整理过的,真实的是不按顺序出现的。

解毕!敬礼!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/15676.html