留言
有逆向题!来劲了,让我看看你有多难,平时做的最多的就是逆向了,还是比较喜欢这个领域。
程序逆向
登录FTP下载Reverse.rar文件,用户名:ftp,密码:空 下载文件并解压。
1.分析程序reverse_0,请找出隐藏信息,并将flag提交。flag格式:flag{<flag值>}
2.分析程序reverse_1,请找出隐藏信息,并将flag提交。flag格式:flag{<flag值>}
3.分析程序reverse_2,请找出隐藏信息,并将flag提交。flag格式:flag{<flag值>}
4.分析程序reverse_3,请找出隐藏信息,并将flag提交。flag格式:flag{<flag值>}
Reverse0 静态分析

1.我已经从FTP服务器下载并解压了文件,现在有几个文件夹可供我查看。首先,让我仔细研究一下reverse0文件夹里的题目。


2.在reverse0文件夹里,我发现了一个Windows PE程序。当我运行该程序并输入几个数字后按回车,程序立刻就退出了。为了更好地了解该程序的工作原理,我决定使用IDA进行代码分析。

3.直接用IDA64位打开,注意:32位和64位程序,架构上是不一样的,我没有用查壳工具进行分析,是因为没有必要,是不是32位或64位程序有没有壳,用IDA一打开就能看的出来的,看提示显示AMD64这就是64位程序了。

4.通过打开程序,我们可以在IDA的流程图中直接看到程序的分析结果。然而,为了让更多人理解分析的过程,我将继续在这里详细分析。

5.通过在流程图界面按F5键,我们可以将反汇编代码转换为C语言代码,这样便于分析。请注意,这种转换可能不完全正确,因此最好保持分析反汇编代码的好习惯。为了节省时间,我们将直接查看转换后的C代码。
int __cdecl main(int argc, const char **argv, const char **envp)
{
int b; // [rsp+28h] [rbp-8h]
int a; // [rsp+2Ch] [rbp-4h]
_main();
scanf("%d%d", &a, &b); // scanf是输入函数 这里传了两个变量 用来接收用户输入的数值
if ( a == b ) // 然后进行判断 a 等于 b 的话 那么就输出 flag。
printf("flag{this_Is_a_EaSyRe}");
else
printf("sorry,you can't get flag"); // 否则就输出不能获取flag 为什么程序会退出呢 打开程序的时候。
return 0; // 输入了数值 直接就退出了,那是因为没有写暂停,即使你输入对了也不会给你看的时间。
}Reverse0 动态调试

6.为了验证程序的行为,我们可以观察到,无论输入什么,程序总是会退出,为了停止它的执行,我们可以在x64dbg的帮助下使用断点,使任务简单而直接。

7.然后按F8单步跳过,不进入call里,直到运行断点下方,scanf输入函数就执行起来了,这个时候我们才可以输入数值。

8.在x64dbg中,按下F8就可以进行单步跳过,不进入被调用的代码段,一直到遇到断点后方的scanf输入函数,此时我们才能输入数值。
flag{this_Is_a_EaSyRe}Reverse1 静态分析

1.通过运行,我们发现程序需要我们输入一个正确的flag,进行判断。因为程序需要判断,所以其中一定包含了正确的flag,与我们输入的flag作比较,然后决定输出正确或错误的结果。

2.让我们使用常用工具IDA来查看一下。打开后,我们意识到没有main函数。所以,我们将直接搜索关键字“flag”,看看是否有任何敏感信息

3.使用快捷键Alt + T,在搜索框中输入关键词'flag'并回车,以查找相关信息。

4.在IDA中, 我们使用alt + T快捷键, 输入关键字"flag"进行查询, 并通过查询发现了程序入口并识别到明显的"input the flag:"关键字. 现在, 我们可以使用F5继续进行分析。
__int64 sub_1400118C0()
{
char *v0; // rdi 定义一个空字符指针
signed __int64 i; // rcx 定义一个64位有符号整数变量
size_t v2; // rax 定义一个无符号v2整数变量
size_t v3; // rax
char v5; // [rsp+0h] [rbp-20h] 定义一个字符v5变量
int j; // [rsp+24h] [rbp+4h]
char Str1; // [rsp+48h] [rbp+28h]
unsigned __int64 v8; // [rsp+128h] [rbp+108h]
v0 = &v5;
for ( i = 82i64; i; --i )
{
*(_DWORD *)v0 = -858993460;
v0 += 4;
}
for ( j = 0; ; ++j )
{
v8 = j;
v2 = j_strlen(Str2);
if ( v8 > v2 )
break;
if ( Str2[j] == 111 )
Str2[j] = 48;
}
sub_1400111D1("input the flag:"); // 这是 printf 提示
sub_14001128F("%20s", &Str1); // 这是 scanf 输入
v3 = j_strlen(Str2); // 这里获取 str2 的长度
if ( !strncmp(&Str1, Str2, v3) ) // 然后判断做比较成立就
sub_1400111D1("this is the right flag!\n"); // 输出正确
else
sub_1400111D1("wrong flag\n"); // 否则就错误
sub_14001113B(&v5, &unk_140019D00);
return 0i64;
}5.我们知道了要进行比较的值,但是不知道str2的值,我们可以通过按住Ctrl键并点击str2参数来查看它的值。

6.进入内存后发现有一串字符串,它是'hello_world',不要以为它就是flag,因为这可能是个误导。
代码分析

#include <stdio.h>
#include <cstring>
int main()
{
char Str2[] = "{hello_world}";
for (int i = 0; i < strlen(Str2); i++)
{
if (Str2[i] == 111) {
Str2[i] = 48;
}
}
printf("%s", Str2);
return 0;
}
/*
根据IDA的分析,代码通过遍历Str2字符串,并在找到字符'o'时将其替换为'0'。接着,代码通过使用strncmp函数进行比较,如果结果为真,就输出"正确"。
*/
Reverse1 动态调试
1.使用xdb64打开目标程序后,首先找到主函数入口。通过按Ctrl + F8让程序自动跳过并在停下时进入被调用的函数。在通过F7一直进入函数直到看到主函数的反汇编段,在 push 代码头部设置断点并单步运行。通过观察寄存器和堆栈里的内容,可以掌握程序执行完成后的结果。
flag{hell0_w0rld}Reverse2 静态分析

1.打开Reverse2题目发现是一个ELF文件,因此xdb64不能进行调试,但是可以使用IDA进行反汇编查看代码。

2.打开ELF文件后,我们可以使用IDA工具查找主函数,通过查看流程图,我们可以发现有关键字的提示。接着我们可以使用快捷键F5将代码转换为C代码,以方便阅读和分析。

int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int stat_loc; // [rsp+4h] [rbp-3Ch]
int i; // [rsp+8h] [rbp-38h]
__pid_t pid; // [rsp+Ch] [rbp-34h]
char s2; // [rsp+10h] [rbp-30h]
unsigned __int64 v8; // [rsp+28h] [rbp-18h]
v8 = __readfsqword(0x28u);
pid = fork();
if ( pid )
{
argv = &stat_loc;
waitpid(pid, &stat_loc, 0);
}
else
{
for ( i = 0; i <= strlen(&flag); ++i ) // 遍历我们输入的flag
{
if ( *(&flag + i) == 105 || *(&flag + i) == 114 ) // 判断存在 i 或者 r
*(&flag + i) = 49; // 成立就替换相应的位置 i 和 r
}
}
printf("input the flag:", argv); // 输出提示
__isoc99_scanf("%20s", &s2); // 输入函数 用来接收 s2 地址的内容
if ( !strcmp(&flag, &s2) ) // 字符flag 与输入的 s2 进行比较
result = puts("this is the right flag!");// 满足条件就成立
else
result = puts("wrong flag!"); // 不满足就错误
return result;
}1.程序通过比较flag与我们输入的s2字符串,但我们不知道s2到底是什么。

2.通过在IDA中使用快捷键 ctrl + 鼠标左键点击 &flag,我们可以查看 s2 存储的字符串 hacking_for_fun},并且结合前面的代码分析可以得出结果。

flag{hack1ng_fo1_fun}Reverse3 静态分析

1.需要使用IDA32打开Reverse3题目,因为它是一个32位的PE程序,架构与其他程序不同。

2.通过使用IDA32,打开Reverse3题目,因为它是一个32位的PE程序,我们可以按F5键将它转换为C代码,以便更好地分析其内部代码实现。
__int64 main_0()
{
size_t v0; // eax
const char *v1; // eax
size_t v2; // eax
int v3; // edx
__int64 v4; // ST08_8
signed int j; // [esp+DCh] [ebp-ACh]
signed int i; // [esp+E8h] [ebp-A0h]
signed int v8; // [esp+E8h] [ebp-A0h]
char Dest[108]; // [esp+F4h] [ebp-94h]
char Str; // [esp+160h] [ebp-28h]
char v11; // [esp+17Ch] [ebp-Ch]
for ( i = 0; i < 100; ++i )
{
if ( (unsigned int)i >= 0x64 )
j____report_rangecheckfailure();
Dest[i] = 0;
}
sub_41132F("please enter the flag:");
sub_411375("%20s", &Str);
v0 = j_strlen(&Str);
v1 = (const char *)sub_4110BE(&Str, v0, &v11);
strncpy(Dest, v1, 0x28u);
v8 = j_strlen(Dest);
for ( j = 0; j < v8; ++j ) // 是在这里做运算了。
Dest[j] += j;
v2 = j_strlen(Dest);
if ( !strncmp(Dest, Str2, v2) ) // dest 与 str2 进行比较 v2 是指定的字符位置
sub_41132F("rigth flag!\n"); // 成立就对了
else
sub_41132F("wrong flag!\n"); // 否则就错误
HIDWORD(v4) = v3;
LODWORD(v4) = 0;
return v4;
}package main
import (
"encoding/base64"
"fmt"
)
var (
count string
str = "e3nifIH9b_C@n@dH"
)
func main() {
for i := 0; i < len(str); i++ {
count += string(int(str[i]) - i)
}
text, err := base64.StdEncoding.DecodeString(count)
if err != nil {
panic(err)
}
fmt.Println(string(text))
}import base64
cont = ''
context = "e3nifIH9b_C@n@dH"
for i in range(0,len(context)):
cont += str(chr(ord(context[i])- i))
print(base64.b64decode(cont).decode())flag{i_l0ve_you}
1.Reverse3题目使用了base64加密,通过ASCII码加循环运算进行加密,我用Go语言写了一个程序解密了它,太晚了,说的不详细,现在要睡了。
Reverse3 动态调试

2.通过动态调试,获得解密结果,提交后得到正确的答案,解题完成。
应急响应
如果是黑客攻击的话,黑客的流量入口一定是通过HTTP服务,这会在HTTP日志中留下痕迹,如上传恶意文件(如webshell,后门,rootkit等),从而导致恶意进程(如CPU利用率),恶意用户攻击路径对应的服务漏洞,以及本地漏洞等问题。
题目1
1.提交攻击者的 IP 地址。

通过研究网页服务,我们可以发现它正在使用Apache,许多软件和服务都有日志记录,我们可以通过分析Apache日志来更好地了解系统运行情况。
cd /var/log/apache2
awk -F " " '{print $1}' access.log.1 | sort | uniq -c
awk -F " " '{print $1" "$4" "$7" "$6}' access.log.1 | sort uniq -c # 多行输出其中,$1、$4、$7、$6 分别代表 Apache access.log 日志文件中的第一个字段,第四个字段第七个字段和第六个字段。

通过分析 Apache 日志,我们可以发现哪个 IP 地址连接次数最多,从而确定是否遭受了攻击。
flag{192.168.1.7}
awk -F " " '{print $7}' access.log.1 | sort | uniq -c题目2
2.识别攻击者使用的操作系统

cat access.log.1 | grep "192.168.1.7" | head -n 1题目3
3.找出攻击者资产收集所使⽤的平台

cat access.log.1 | grep "https"题目4
4.提交攻击者目录扫描所使用的工具名称
常见的扫描工具
dirsearch
dirb
gobuster
dirbuster
ffuf
wfuzz
题目5
5.提交攻击者首次攻击成功的时间,格式:DD/MM/YY:HH:MM:SS

题目6
6.找到攻击者写入的恶意后的文件,提交⽂件名(完整路径)和后门密码 1.php

grep -r "eval(" /var/www题目7
7.找到攻击者隐藏在正常web应用代码中的恶意代码,提交该文件名(完整路径) footer.php

find . -name "*.php" | grep "1"题目8-9-10
8.识别系统中存在的恶意程序进程,提交进程名 ./prism
9.找到⽂件系统中的恶意程序文件并提交⽂件名(完整路径)prism
10.简要描述该恶意⽂件的⾏为

crontab -l # 列出启动项
crontab -e # 编辑启动项通过观察系统任务周期,我们可以发现 Prism 程序的存在以及它的路径。

find / -name prism
cd /root/.mal/
./prism inf0通过分析任务周期,可以确定程序的名称为 prism,在这个目录下,可以使用搜索功能找到 prism 并进入该目录,使用 history 命令查看过去的输入历史,以找到 prism 的运行参数,最后运行该程序,观察是否有任何变化。
恶意行为
运行恶意二进制文件,使用sh shell启动一个bind shell,等待恶意IP的连接,输入对应的密码即可与该shell建立连接。
答题系统
方法1


1.将解压后的源代码放入 phpstudy 服务器中,直接可以通过浏览器访问,"可以发现,该网站每三秒就会刷新一次,因此,我们需要做的是在三秒内作答并提交答案,以获得flag,由于人类难以计算,因此,我们可以利用编程或工具的力量来解决问题。
import requests, re
def main():
session = requests.Session()
response = session.get("http://10.60.47.126:81/index.php")
html = re.compile(r'<h2.*?>(.*?)</h2>', re.S)
res = html.search(response.text).group(1)
clac = re.sub("x","*", res)
data = {
'answer': eval(clac[:-3])
}
answer = session.post("http://10.60.47.126:81/check.php", data=data)
print(answer.text)
if __name__ == '__main__':
main()
方法2

F12打开浏览器调试工具,在控制台中输入延迟函数 stop(100000),延迟网页刷新速度进行即可计算答题。


流量分析
题目1
从靶机服务器的 FTP 上下载capture.pcapng数据包,账号名:ftp,密码:空,使用
Wireshark分析数据包找出telnet服务器(路由器)的用戶名和密码,并将密码作为Flag值
提交。flag格式:flag{密码}


通过使用关键字搜索,我们可以发现相关的数据包。关键字 “invalid” 表示错误,而 “success” 则代表正确。我们可以使用过滤语句,追踪TCP流,逐个搜索关键字即可。
/*
telnet 账号:admin
telnet 密码:Cisc0
*/
flag{Cisc0}题目2
使用Wireshark分析capture.pcapng数据流量包,telnet服务器是一台路由器,找出此台路
由器的特权密码,并将密码作为Flag值提交。flag格式:flag{密码}
通过对第一个问题的分析,我们获得了特权访问的密码。
flag{cisco123}题目3

通过结合协议和 IP 地址进行筛选,可以发现有 145 个数据包显示。这样就完成了分析。
telnet and ip.src == 192.168.181.141flag{145}题目4

通过过滤出 FTP 的命令,发现数量很少,可以用人眼手动分析。
flag{PORT 192,168,181,1,235,130}题目7
使用Wireshark分析capture.pcapng数据流量包,web服务器地址是192.168.181.250,其使用的
脚本语言为php,将服务器使用php的版本号作为Flag值提交。flag格式:flag{php版本号}

ip.src == 192.168.181.250 and httpflag{5.5.38}题目8
使用Wireshark分析capture.pcapng数据流量包,web服务器地址是192.168.181.250,将web服务器软件的版本号作为Flag值提交。flag格式:flag{web软件版本号}

ip.addr == 192.168.181.250 and http contains "Server"flag{2.2.15}题目9
使用Wireshark分析capture.pcapng数据流量包,找出数据包当中所有HTTP状态码为404
的报文,将这些报文的数量作为Flag值提交。flag格式:flag{报文数量}
...
题目11
使用Wireshark分析capture.pcapng数据包文件,这些数据中有非常多的ICMP报文,这些
报文中有大量的非正常ICMP报文,找出类型为重定向的所有报文,将报文重定向的数量作
为Flag值提交。flag格式:flag{重定向数量}

0:Echo Reply (回显应答)
3:Destination Unreachable(目标不可达)
5:Redirect(重定向)
8:Echo Request(回显请求)
11:Time Exceeded(超时)
13:Timestamp Request(时间戳请求)
14:Timestamp Reply(时间戳应答)
15:Information Request(信息请求)
16:Information Reply(信息应答)
icmp.type eq 5flag{57}
评论 (0)