ez_mem&usb writeup

知识点:

  • 内存取证(volatility使用)
  • usb流量取证

解题过程:

我们拿到手的是一个pcap包:

看到流量包首先使用wireshark打开,随便追踪一个数据流就会发现这里面的交互中有一个压缩包:

所以我们先导出http对象看一下,发现有一个php特别大,直觉告诉我们肯定有问题,很有可能这里面就包含着我们想要的压缩包:

保存upload_file.php之后,使用binwalk查看,果然里面含有压缩包。使用foremost分离后得到一个vmem文件

(但是很奇怪的是,我使用winhex手动对pcap文件进行分离总是失败,使用foremost分离pcap也不行,会报出压缩包数据格式损坏,但是对upload_file.php分离就可以。难道是因为pcap中还是加密的数据吗?不懂,希望有大佬可以帮忙解释一下)

得到data.vmem之后,很明显考察方向是内存取证。内存取证一般使用volatility,很强大的工具,Kali中有自带。

首先查看一下进程树:

没发现有什么特别的内容,我们可以再看一下cmd的历史操作:

在我们能看到的内容里,发现有一个密码passwd:weak_auth_top100,然后打开了wireshark,可以知道它捕获了流量。一般来说passwd都是很关键的信息,现在我们还不知道有什么用,暂且搁置。

接下来可以扫描一下内存里面的文件:

发现了一个flag.img,既然跟flag有关,那么就先导出来看看吧:

这时候会发现你的文件夹中多了一个.dat文件。接下来我们可以对这个文件进行分析。

同样binwalk看完之后发现有一个zip文件,我们使用foremost分离,提取出一个压缩包。

解压时用到了我们之前在cmd中找到的密码。

压缩包内是一个txt文件,内容如下:

结合题目,可以想到这是一个usb流量数据包。这里的数据都集中在了第三键上,说明是一个键盘流量。对照分析表,可以写出代码解码。

说明:

1. 键盘数据包的数据长度为8个字节,击键信息集中在第3个字节,每次key stroke都会产生一个keyboard event usb packet。

2. 鼠标数据包的数据长度为4个字节,第一个字节代表按键,当取0x00时,代表没有按键、为0x01时,代表按左键,为0x02时,代表当前按键为右键。第二个字节可以看成是一个signed byte类型,其最高位为符号位,当这个值为正时,代表鼠标水平右移多少像素,为负时,代表水平左移多少像素。第三个字节与第二字节类似,代表垂直上下移动的偏移。

分析表:

代码:

# coding:utf-8
import sys
import os

usb_codes = {
    0x04: "aA", 0x05: "bB", 0x06: "cC", 0x07: "dD", 0x08: "eE", 0x09: "fF",
    0x0A: "gG", 0x0B: "hH", 0x0C: "iI", 0x0D: "jJ", 0x0E: "kK", 0x0F: "lL",
    0x10: "mM", 0x11: "nN", 0x12: "oO", 0x13: "pP", 0x14: "qQ", 0x15: "rR",
    0x16: "sS", 0x17: "tT", 0x18: "uU", 0x19: "vV", 0x1A: "wW", 0x1B: "xX",
    0x1C: "yY", 0x1D: "zZ", 0x1E: "1!", 0x1F: "2@", 0x20: "3#", 0x21: "4$",
    0x22: "5%", 0x23: "6^", 0x24: "7&", 0x25: "8*", 0x26: "9(", 0x27: "0)",
    0x2C: "  ", 0x2D: "-_", 0x2E: "=+", 0x2F: "[{", 0x30: "]}", 0x32: "#~",
    0x33: ";:", 0x34: "'\"", 0x36: ",<", 0x37: ".>", 0x4f: ">", 0x50: "<"
}


def code2chr(filepath):
    lines = []
    pos = 0
    for x in open(filepath, "r").readlines():
        code = int(x[6:8], 16)  # 即第三个字节
        if code == 0:
            continue
        # newline or down arrow - move down
        if code == 0x51 or code == 0x28:
            pos += 1
            continue
        # up arrow - move up
        if code == 0x52:
            pos -= 1
            continue

        # select the character based on the Shift key
        while len(lines) <= pos:
            lines.append("")
        if code in range(4, 81):
            if int(x[0:2], 16) == 2:
                lines[pos] += usb_codes[code][1]
            else:
                lines[pos] += usb_codes[code][0]

    for x in lines:
        print(x)


if __name__ == "__main__":
    code2chr('E://CTF练习/杂项/18e4c103d4de4f07b33a42cb1f0eaa1d/00000122/usbdata.txt')

关于USB流量:

USB 接口是目前最为通用的外设接口之一,通过监听该接口的流量,可以得到很多有意思的东西,例如键盘击键,鼠标移动与点击,存储设备的明文传输通信、USB 无线网卡网络传输内容等。使用wireshark就可以捕获。

USB有不同的规格,比较常见的有以下三种:

USB USRT:这种方式下,设备只是简单的将USB用于接受和发射数据,除此之外就再没有其他通讯功能了。

USB HID:人性化的接口。这一类通讯适用于交互式,有这种功能的设备有:键盘,鼠标,游戏手柄和数字显示设备。

USB Memory:数据存储。External HDD, thumb drive / flash drive,等都是这一类的。

可以使用Wireshark分析USB流量,USB协议的数据部分在Leftover Capture Data域之中,在Mac和Linux下可以用tshark命令可以将 leftover capture data单独提取出来,命令如下:

tshark -r example.pcap -T fields -e usb.capdata

在Windows下去tshark.exe的目录下输入上面的命令即可。

给下列代码加注释和图形化界面module fifo #( parameter integer DWIDTH = 32, parameter integer AWIDTH = 4 ) ( input clock, reset, wr_en, rd_en, input [DWIDTH-1:0] data_in, output f_full, f_empty, output [DWIDTH-1:0] data_out ); reg [DWIDTH-1:0] mem [0:2**AWIDTH-1]; //parameter integer DEPTH = 1 << AWIDTH; //wire [DWIDTH-1:0] data_ram_out; //wire wr_en_ram; //wire rd_en_ram; reg [AWIDTH-1:0] wr_ptr; reg [AWIDTH-1:0] rd_ptr; reg [AWIDTH-1:0] counter; wire [AWIDTH-1:0] wr; wire [AWIDTH-1:0] rd; wire [AWIDTH-1:0] w_counter; //Write pointer always@(posedge clock) begin if (reset) begin wr_ptr <= {(AWIDTH){1'b0}}; end else if (wr_en && !f_full) begin mem[wr_ptr]<=data_in; wr_ptr <= wr; end end //Read pointer always@(posedge clock) begin if (reset) begin rd_ptr <= {(AWIDTH){1'b0}}; end else if (rd_en && !f_empty) begin rd_ptr <= rd; end end //Counter always@(posedge clock) begin if (reset) begin counter <= {(AWIDTH){1'b0}}; end else begin if (rd_en && !f_empty && !wr_en) begin counter <= w_counter; end else if (wr_en && !f_full && !rd_en) begin counter <= w_counter; end end end assign f_full = (counter == 4'd15)?1'b1:1'b0;//DEPTH- 1) ; assign f_empty = (counter == 4'd0)?1'b1:1'b0;//{AWIDTH{1'b0}}); assign wr = (wr_en && !f_full)?wr_ptr + 4'd1:wr_ptr + 4'd0; assign rd = (rd_en && !f_empty)?rd_ptr+ 4'd1:rd_ptr+ 4'd0; assign w_counter = (rd_en && !f_empty && !wr_en)? counter - 4'd1: (wr_en && !f_full && !rd_en)? counter + 4'd1: w_counter + 4'd0; //assign wr_en_ram = wr_en; //assign rd_en_ram = rd_en; assign data_out = mem[rd_ptr];//data_ram_out; /* dp_ram #(DWIDTH, AWIDTH) RAM_1 ( .clock(clock), .reset(reset), .wr_en(wr_en_ram), .rd_en(rd_en_ram), .data_in(data_in), .wr_addr(wr_ptr), .data_out(data_ram_out), .rd_addr(rd_ptr) ); */ endmodule
最新发布
05-29
下面是对该FIFO模块的注释: ```verilog module fifo #( parameter integer DWIDTH = 32, parameter integer AWIDTH = 4 ) ( input clock, reset, wr_en, rd_en, input [DWIDTH-1:0] data_in, output f_full, f_empty, output [DWIDTH-1:0] data_out ); reg [DWIDTH-1:0] mem [0:2**AWIDTH-1]; // 声明一个深度为2**AWIDTH的寄存器数组,存储输入数据 reg [AWIDTH-1:0] wr_ptr; // 声明写指针,用于指向写入数据的位置 reg [AWIDTH-1:0] rd_ptr; // 声明读指针,用于指向读取数据的位置 reg [AWIDTH-1:0] counter; // 声明计数器,用于记录队列中的数据数量 wire [AWIDTH-1:0] wr; // 声明一个组合逻辑变量,用于计算写指针的值 wire [AWIDTH-1:0] rd; // 声明一个组合逻辑变量,用于计算读指针的值 wire [AWIDTH-1:0] w_counter; // 声明一个组合逻辑变量,用于计算计数器的值 // 写指针逻辑 always@(posedge clock) begin if (reset) begin wr_ptr <= {(AWIDTH){1'b0}}; // 初始化写指针为0 end else if (wr_en && !f_full) begin mem[wr_ptr] <= data_in; // 将输入数据存储到内存中 wr_ptr <= wr; // 更新写指针的值 end end // 读指针逻辑 always@(posedge clock) begin if (reset) begin rd_ptr <= {(AWIDTH){1'b0}}; // 初始化读指针为0 end else if (rd_en && !f_empty) begin rd_ptr <= rd; // 更新读指针的值 end end // 计数器逻辑 always@(posedge clock) begin if (reset) begin counter <= {(AWIDTH){1'b0}}; // 初始化计数器为0 end else begin if (rd_en && !f_empty && !wr_en) begin // 如果只有读操作,则计数器减1 counter <= w_counter; end else if (wr_en && !f_full && !rd_en) begin // 如果只有写操作,则计数器加1 counter <= w_counter; end end end assign f_full = (counter == 4'd15) ? 1'b1 : 1'b0; // 如果队列满了,则输出f_full assign f_empty = (counter == 4'd0) ? 1'b1 : 1'b0; // 如果队列为空,则输出f_empty assign wr = (wr_en && !f_full) ? wr_ptr + 4'd1 : wr_ptr + 4'd0; // 如果队列未满,则写指针+1 assign rd = (rd_en && !f_empty) ? rd_ptr + 4'd1 : rd_ptr + 4'd0; // 如果队列非空,则读指针+1 assign w_counter = (rd_en && !f_empty && !wr_en) ? counter - 4'd1 : // 如果只有读操作,则计数器减1 (wr_en && !f_full && !rd_en) ? counter + 4'd1 : // 如果只有写操作,则计数器加1 w_counter + 4'd0; // 如果既有读操作又有写操作,则计数器不变 assign data_out = mem[rd_ptr]; // 从内存中读取数据,并输出到data_out // RAM组件,用于存储数据,这里被注释掉了 /* dp_ram #(DWIDTH, AWIDTH) RAM_1 ( .clock(clock), .reset(reset), .wr_en(wr_en_ram), .rd_en(rd_en_ram), .data_in(data_in), .wr_addr(wr_ptr), .data_out(data_ram_out), .rd_addr(rd_ptr) ); */ endmodule ``` 由于该FIFO模块没有提供图形化界面,所以无法生成图形化界面展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值