【CTF解题】2022浙江省信息安全管理与评估解题
【CTF解题】2022浙江省信息安全管理与评估解题
2022-12-08 / 0 评论 / 899 阅读 / 113 点赞

【CTF解题】2022浙江省信息安全管理与评估解题

发光的神
2022-12-08 / 0 评论 / 899 阅读 / 正在检测是否收录...

留言

有逆向题!来劲了,让我看看你有多难,平时做的最多的就是逆向了,还是比较喜欢这个领域。

程序逆向

登录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 静态分析

lbeq5g0f.png

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

lbeqe9v4.png

lber1r4z.png

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

lbeqi5ew.png

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

lbeqrivp.png

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

lbequ84u.png

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 动态调试

lberv43l.png

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

lbes4ju2.png

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

lbes703k.png

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

flag{this_Is_a_EaSyRe}

Reverse1 静态分析

lbet3xty.png

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

lbeswxtt.png

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

lbet08yq.png

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

lbet2t7p.png

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参数来查看它的值。

lbetj8xs.png

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

代码分析

lbet93ku.png

#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函数进行比较,如果结果为真,就输出"正确"。
*/

lbhuohox.png

Reverse1 动态调试

1.使用xdb64打开目标程序后,首先找到主函数入口。通过按Ctrl + F8让程序自动跳过并在停下时进入被调用的函数。在通过F7一直进入函数直到看到主函数的反汇编段,在 push 代码头部设置断点并单步运行。通过观察寄存器和堆栈里的内容,可以掌握程序执行完成后的结果。

flag{hell0_w0rld}

Reverse2 静态分析

lbhyy2ij.png

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

lbhzdm2p.png

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

lbhzcmo3.png

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到底是什么。

lbhzpqzx.png

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

ldtyki88.png

flag{hack1ng_fo1_fun}

Reverse3 静态分析

lbhzw50x.png

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

lbhzwgmj.png

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}

lbi1bacr.png

1.Reverse3题目使用了base64加密,通过ASCII码加循环运算进行加密,我用Go语言写了一个程序解密了它,太晚了,说的不详细,现在要睡了。

Reverse3 动态调试

lbi1iyn1.png

2.通过动态调试,获得解密结果,提交后得到正确的答案,解题完成。

应急响应

如果是黑客攻击的话,黑客的流量入口一定是通过HTTP服务,这会在HTTP日志中留下痕迹,如上传恶意文件(如webshell,后门,rootkit等),从而导致恶意进程(如CPU利用率),恶意用户攻击路径对应的服务漏洞,以及本地漏洞等问题。

题目1

1.提交攻击者的 IP 地址。

ldmz4h2v.png

通过研究网页服务,我们可以发现它正在使用Apache,许多软件和服务都有日志记录,我们可以通过分析Apache日志来更好地了解系统运行情况。

cd /var/log/apache2

ldmzlo21.png

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 日志文件中的第一个字段,第四个字段第七个字段和第六个字段。

ldmzomfd.png

通过分析 Apache 日志,我们可以发现哪个 IP 地址连接次数最多,从而确定是否遭受了攻击。

flag{192.168.1.7}

ldn01y13.png

awk -F " " '{print $7}' access.log.1 | sort | uniq -c

题目2

2.识别攻击者使用的操作系统

ldn0wan6.png

cat access.log.1 | grep "192.168.1.7" | head -n 1

题目3

3.找出攻击者资产收集所使⽤的平台

lui9ekeu.png

cat access.log.1 | grep "https"

题目4

4.提交攻击者目录扫描所使用的工具名称

常见的扫描工具

dirsearch
dirb
gobuster
dirbuster
ffuf
wfuzz

ldn1r34b.png

题目5

5.提交攻击者首次攻击成功的时间,格式:DD/MM/YY:HH:MM:SS

ldn170hi.png

题目6

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

ldn1amgo.png

grep -r "eval(" /var/www

题目7

7.找到攻击者隐藏在正常web应用代码中的恶意代码,提交该文件名(完整路径) footer.php

lep06wio.png

find . -name "*.php" | grep "1"

题目8-9-10

8.识别系统中存在的恶意程序进程,提交进程名 ./prism
9.找到⽂件系统中的恶意程序文件并提交⽂件名(完整路径)prism
10.简要描述该恶意⽂件的⾏为

ldntcg2h.png

crontab -l # 列出启动项
crontab -e # 编辑启动项

通过观察系统任务周期,我们可以发现 Prism 程序的存在以及它的路径。

ldntmucb.png

find / -name prism
cd /root/.mal/
./prism inf0

通过分析任务周期,可以确定程序的名称为 prism,在这个目录下,可以使用搜索功能找到 prism 并进入该目录,使用 history 命令查看过去的输入历史,以找到 prism 的运行参数,最后运行该程序,观察是否有任何变化。

恶意行为

运行恶意二进制文件,使用sh shell启动一个bind shell,等待恶意IP的连接,输入对应的密码即可与该shell建立连接。

答题系统

方法1

ldkzdomn.png

ldkznoa6.png

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()

ldkzk6vb.png

方法2

ldr7b5l0.png

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

ldr8h2mt.png

ldr8hi4e.png

流量分析

题目1

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

lb3pm7i4.png

lb3pv8ly.png

通过使用关键字搜索,我们可以发现相关的数据包。关键字 “invalid” 表示错误,而 “success” 则代表正确。我们可以使用过滤语句,追踪TCP流,逐个搜索关键字即可。

/*
  telnet 账号:admin
  telnet 密码:Cisc0
*/
flag{Cisc0}

题目2

使用Wireshark分析capture.pcapng数据流量包,telnet服务器是一台路由器,找出此台路
由器的特权密码,并将密码作为Flag值提交。flag格式:flag{密码}

通过对第一个问题的分析,我们获得了特权访问的密码。

flag{cisco123}

题目3

lb3q5pbp.png

通过结合协议和 IP 地址进行筛选,可以发现有 145 个数据包显示。这样就完成了分析。

telnet and ip.src == 192.168.181.141
flag{145}

题目4

lb3qmumt.png

通过过滤出 FTP 的命令,发现数量很少,可以用人眼手动分析。

flag{PORT 192,168,181,1,235,130}

题目7

使用Wireshark分析capture.pcapng数据流量包,web服务器地址是192.168.181.250,其使用的
脚本语言为php,将服务器使用php的版本号作为Flag值提交。flag格式:flag{php版本号}

lef6rmwd.png

ip.src == 192.168.181.250 and http
flag{5.5.38}

题目8

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

lef6koz7.png

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{重定向数量}

lef5kg9o.png

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 5
flag{57}
113

评论 (0)

取消
0:00