好玩的任务之简单防火墙配置与简单C语言代码缓冲区溢出分析

任务

  1. 配置Windows防火墙,开放8080端口、阻断3389端口
  2. 运行三段代码,对结果进行分析,第一段代码分析输出结果出现的原理,解释第二段代码和第三段代码的不同之和原因
 //第一段代码
 #include<stdio.h>
 #include<stdlib.h>
 #include<stdint.h>
 void here()
 {
    printf("hello,i am here ?\n");
    exit(0);
 }
 ​
 void main()
 {
    uintptr_t buf[2];
    buf[3]=(uintptr_t)here;
    return;
 }
 //第二段代码
 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 #define size 32
 int main(int argc, char **argv){
     char *buf1;
     char *buf2;
     buf1 = (char*) malloc(size);
     free(buf1);  
     buf1=NULL;
     buf2 = (char *) malloc(size);
     memset(buf2, 0, size);
     printf("buf2: %d\n", *buf2);
     printf("==== Use After Free ===\n");
     strncpy(buf1, "info", 5);
     printf("buf2: %s\n\n", buf2);
     free(buf2);
 }
 //第三段代码
 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
 #define size 32
 int main(int argc, char **argv){
     char *buf1;
     char *buf2;
     buf1 = (char*) malloc(size);
     free(buf1);  
     buf2 = (char *) malloc(size);
     memset(buf2, 0, size);
     printf("buf2: %d\n", *buf2);
     printf("==== Use After Free ===\n");
     strncpy(buf1, "info", 5);
     printf("buf2: %s\n\n", buf2);
     free(buf2);
 }

任务一 操作

打开控制面板

控制面板\系统和安全\Windows Defender 防火墙

选择高级设置

入站规则 -> 新建规则

根据以下配置修改

Allow_8080

  • 规则类型:端口
  • 协议和端口:TCP 特定端口:8080
  • 操作:允许连接
  • 作用域:全部
  • 名称:Allow_8080

Block_389

  • 规则类型:端口
  • 协议和端口:TCP 特定端口 3389
  • 操作:阻止连接
  • 作用域:全部
  • 名称:Block_3389

任务二

第一段代码运行结果

首先对代码进行审计,坦白来说一开始看到这串代码是有点懵的,和我们最常见的c语言代码有点区别,main函数的返回值是空,并且uintptr_t这个关键字没见过

查询资料

c语言程序运行时,是操作系统将main作为程序的“入口点”,自动启动执行main函数

标准c规定,main的返回值必须是int(即int mian),因为程序结束时,需要通过return的值或exit()的参数向操作系统返回“执行状态”比如return 0表示正常结束,return 非0表示异常结束);

void main()是某些编译器的 “非标准扩展”(比如老版本的 VC++),虽然可能编译通过,但移植性极差,不建议写。

uintptr_t: 是 C 语言(C99 及以后标准)中定义在 <stdint.h> 头文件里的专用无符号整数类型,存储指针的整数地址宽度和当前系统的指针完全一致(32 位系统占 4 字节,64 位系统占 8 字节)

原代码定义了一个here函数,用于输出hello,i am here ?,后退出程序,主函数定义了一个无符号整数类型的数组buf,但是出现了一个非法的操作

 buf[3] = (uintptr_t)here;

出现了缓冲区溢出,导致程序输出了hello,i am here ?

后面使用pwndbg对程序的运行过程进行调试分析

 pwndbg> break main

main() 函数入口(或第一条指令)设置断点,让程序在“出错之前”停下来

 pwndbg> run

从头运行程序,这次会停在 main

 pwndbg> print &buf
 $1 = (uintptr_t (*)[2]) 0x7fffffffe250

buf起始地址0x7fffffffe250

 pwndbg> info frame

看见了关键信息

 Saved registers:
  rbp at 0x7fffffffe260
  rip at 0x7fffffffe268

说明返回地址(saved RIP)存在 于0x7fffffffe268

 pwndbg> x/gx $rbp+8
 0x7fffffffe268: 0x00007ffff7c2a1ca

得知$rbp+8 = 当前函数保存返回地址的内存位置

 pwndbg> next

继续执行代码,让越界发生,再次使用命令

 pwndbg> x/gx $rbp+8
 0x7fffffffe268: 0x0000000000401156
 pwndbg> print here
 $2 = {void ()} 0x401156 <here>

此时返回地址的值于here的地址完全一样,说明数组越界刚好写到了函数返回时要用的地址,也就是说,buf[3]对应的内存地址于函数栈帧中保存返回地址的位置一致,程序执行越界写入操作后,该地址被修改为here()的地址,从而导致函数return时,程序执行流发生改变,执行here函数

第二段代码和第三段代码不同之处和原因

代码二和代码三的运行结果区别

区别在于代码二的

 buf1 = NULL; 

free:释放这块内存

buf1 = NULL主动断开指针与已释放内存的关系

再次使用 buf1:等价于对 NULL 指针写数据,属于 非法内存访问,程序行为未定义

而代码三

 free(buf1);
 // buf1 仍然是一个“看起来正常的地址”
 strncpy(buf1, "info", 5);

第二段代码在释放 buf1 后将指针置为 NULL,再次使用该指针会导致对空指针的非法访问,错误容易被发现;第三段代码释放 buf1 后未将指针清空,形成悬空指针,当后续 malloc 复用同一内存区域时,通过已释放指针写入的数据会影响新的对象,属于典型的 Use-After-Free 漏洞,错误更加隐蔽且危险。





✍️ 好玩的任务之简单防火墙配置与简单C语言代码缓冲区溢出分析



暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇