1.攻防世界Re.logmein wp
发现 该文件为64位的ELF文件,然后再使用 64 位的 IDA Pro 打开,由于需要首先寻找看程序是否有提示信息,所以使用 shift+F12 打开字符串窗口,以看到有关“correct password”的提示信息,双击跟进,转换为伪代码
发现算法的关键在于 V6、V7、V8 的异或处理,通过分析得到如下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BYTE unsigned char
int main(int argc, char* argv[]) {
unsigned int i;
char v8[18] = ":\"AL_RT^L*.?+6/46";
__int64 v7 = 28537194573619560;
int v6 = 7;
char s[18] = "";
for (i = 0; i < strlen(v8); ++i) {
s[i] = (char)(*((BYTE*)&v7 + i % v6)^v8[i]);
}
printf("%s\n", s);
system("PAUSE");
return 0;
}
2.逆向工程核心原理学习记录
2.1用打补丁方式修改“Hello world!”
2.2了解IA-32寄存器
2.3使用OD对栈进行了简单的操作与分析
2.4逆向工程核心原理到P41
2.5加密与解密中关于动态分析的部分
1.OllyDbg常用的快捷键
01 F2 断点,在OllyDBG反汇编视图中,使用F2指定断点地址
02 F3 加载一个可执行程序,进行调试分析
03 F4 程序执行到光标处
04 F5 缩小、还原当前窗口
05 F7 单步步入,进入函数实现内,跟进到CALL地址处
06 F8 单步步过,越过函数实现,CALL指令不会跟进函数实现
07 F9 直接运行程序,遇到断点处,程序暂停
08 Ctrl+F2 重新运行到程序起始处,用于重新调试程序
09 Ctrl+F9 执行到函数返回处,用于跳出函数实现
10 Alt+F9 执行到用户代码处,用于快捷跳出系统函数
11 Ctrl+G 输入十六进制地址,在反汇编或数据窗口中快速定位到该地址处
2.PE(Portable Execute)文件被称为可移植的执行体(可执行文件),像我们平常所见的.exe.dll都是PE文件,PE文件是微软Windows平台操作系统上的可执行程序文件。 PE文件能被Windows平台的操作系统解释并执行,因此有固定的文件格式。PE 文件格式被组织为一个线性的数据流,它由一个MS-DOS 头部开始,接着是一个实模式的程序残余以及一个PE 文件标志,这之后紧接着PE文件头和可选头部。这些之后是所有的段头部,段头部之后跟随着所有的段实体。文件的结束处是一些其它的区域,其中是一些混杂的信息,包括重分配信息、符号表信息、行号信息以及字串表数据。
3.大端字节序和小端字节序(存储的大小端问题)
- 大端(存储)模式:是指一个数据的低位字节序的内容放在高地址处,高位字节序存的内容放在低地址处。
- 小端(存储)模式:是指一个数据的低位字节序内容存放在低地址处,高位字节序的内容存放在高地址处。(可以总结为“小小小”即低位、低地址、小端)
4. 常见的汇编指令
CALL XXXX //调用XXXX地址处的函数
JMP XXXX // 跳转到XXXX地址处
PUSH XXXX //保存XXXX到栈(入栈)
POP XXXX //弹出XXXX地址(出栈)
RETN XXXX //跳转到栈中保持的地址础的结构.
5.win32API函数
API函数,操作系统除了协调应用程序的执行、内存分配、系统资源管理外,同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务是一个函数),可以帮助应用程序达到开启视窗、描绘图形、使用周边设备的目的,由于这些函数服务的对象是应用程序(Application),所以称之为Application Programming Interface,简称API函数。
wow64
WOW64 (Windows-on-Windows 64-bit)是一个Windows操作系统的子系统, 它为现有的 32 位应用程序提供了 32 位的模拟,可以使大多数 32 位应用程序在无需修改的情况下运行在 Windows 64 位版本上。
WOW64 是在用户模式下实现的,作为 ntdll.dll 和内核之间的层。WOW64 及其支持的一些 DLL 仅仅是可以加载到 32 位进程中的 64 位的 DLL。对于所有其他情况,进程保持为纯进程。32 位的进程无法加载 64 位的 DLL,反之亦然。
6.logmein wp
先查壳,确定是没有加壳的64位文件。
用ida打开查看主函数,发现当输入的s满足关键条件(s[ i ] == (char)(((_BYTE *)&v7 + i % v6) ^ v8[ i ]))的时候就correct。
由此写出一个倒推出s的程序,运行得到 flag :
1.文件中v8定义的长度是8,因为strcpy( v8, “…”) 中赋给v8的字符串长度(18)超出了定义的范围,v8实际存储的是整个字符串,所以strlen(v8)==18。
2.第一次运行的时候v7初始化为“ ebmarah ”,结果出现乱码,猜测该文件采用了小端模式存储变量,即在低地址存放低位数据。所以猜测正确的v7应该是倒着读的“ ebmarah ”。
3.由文件的第一个 if 可知 s 的长度 >= 18,由第二个 if 可知 (s 的长度-1 ) < 18,可推测 s 的长度也为18。所以让循环体循环18次。
7.getit wp
先查壳,是64位未加壳的文件。用ida打开查看主函数:
1.查看变量s的内容,用快捷键“ * ”查看其长度:33。因v5从0开始+1,所以循环总共进行33次。
2.查看 t 的内容,是一个char字符,地址+10刚好到下一个变量 harifctf{…} 括号的内容。用地址间的差值可算得括号里的内容共33个字符,推测该循环体是对 s 进行加密后存储到 harifctf 中。
3.之后的函数利用了地址的偏移把字符一个个写到stream指向的位置上。写进去的字符的地址偏移与当前指针的偏移是相同的,所以此处并没有进行加密,相当于把 t 地址之后的内容赋值到flag文件中:
最后再写一个推算出括号内容的程序:
最后把它放到括号中,flag还要加上字符t存储的字符‘S’,因为在写进去的时候是从t开始写的:
SharifCTF{b70c59275fcfa8aebf2d5911223c6589}