欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pwnable.kr-coin1 WP

程序员文章站 2022-05-15 14:22:02
...

首先看一下题目

pwnable.kr-coin1 WP

题目的意思是让你玩一个游戏,给你一些金币,其中有一个假币,这个假币外表和真的金币一样,但是重量不同,真的金币重量为10,假币重量为9。你需要帮他找到100枚假币才能过关。

游戏规矩如下:

  1. 给你N枚硬币和C次机会
  2. 选择硬币的序号,称重
  3. 你获得硬币的重量
  4. 第二步第三步重复C次,然后你给出正确答案(也就是哪一枚是假币)

下面给出了一个列子,比如给你4枚硬币,2次机会,你第一次选择称重序号为0,1的硬币,返回给你他们的重量为20(也就是0,1这两枚硬币为真的),然后重复第二步第三步,这时你选择了序号为3的硬币去称重,返回结果为10,说明序号为2的硬币为假的(注意题干,真硬币重量为10,假硬币重量为9),然后你将假币的序号发送给他,他会返回给你“Correct!”

这道题没有涉及到漏洞方面的知识,就是锻炼你用pwntools去交互,以及使用了二分查找这个算法。例子已经隐约的给出提示用二分法了,二分查找也就折半查找,是一种效率较高的查找方法,他查找的次数最多为
log2(n+1) \lceil log_2(n+1)\rceil

对于二分查找不太了解的可以去百度搜索一下相关资料,下面是这道题的脚本

from pwn import *
import re

#将日志等级设置为debug,为了将交互的消息打印到屏幕,方便调试
context.log_level = 'debug'

conn = remote('pwnable.kr', 9007)

conn.recvuntil("Ready?")

#匹配模式,匹配N和C的值
start_match = """N=(\d+) C=(\d+)"""
while True:
	line = conn.recvline_regex(start_match)
	result = re.search(start_match, line)
	n,c = result.groups()
	n = int(n)
	c = int(c)
	print n,c
	
    #设置初始区间
	start = 0
	end = n-1
	
	for i in xrange(c):
		#取区间中间点
		mid = (start + end) / 2
		print "Round", 1, start, mid, end

		#将(start,mid+1)输入到服务器
		coins_to_test = [str(i) for i in xrange(start, mid+1)]
		output = " ".join(coins_to_test)
		conn.sendline(output)
		
        #匹配返回值(重量)        
		response_match = """(\d+)"""
		line = conn.recvline()
		result = re.search(response_match, line)

		weight = int(result.groups()[0])
		expected_weight = len(coins_to_test) * 10

		print expected_weight, weight

		#检测返回结果,更新区间
		if weight == expected_weight:
			start = mid + 1
			end = end
		else:
			start = start
			end = mid

	#最后给出我们的选择(哪一个是假币)
	conn.sendline(str(start))
	conn.recvuntil("Correct!")

运行一下,提示超时报错,应该是网络延迟造成的,这里我们用之前的账号登录进去,在/tmp目录下创建个自己的目录,将脚本传入这个目录,在本地执行脚本。既然在本机执行,那么连接的语句(conn = remote('pwnable.kr', 9007))需要修改一下,改成conn = remote('127.0.0.1', 9007)。这里我用的是fd的账号登录的,在/tmp下创建了cusuall目录,将脚本传进去跑一下就出结果了。

pwnable.kr-coin1 WP
pwnable.kr-coin1 WP

pwnable.kr-coin1 WP