猿人學(xué)之雪碧圖樣式干擾

篇幅有限

完整內(nèi)容及源碼關(guān)注公眾號:ReverseCode,發(fā)送

題目

https://match.yuanrenxue.com/match/4

image-20210917162428942

抓包

https://match.yuanrenxue.com/api/match/4

image-20210917162624937

分析

image-20210917162856315

該頁面每個(gè)td中img個(gè)數(shù)和實(shí)際展示個(gè)數(shù)不一致,且部分img被display: none;屬性隱藏后個(gè)數(shù)一致,但img排列組合順序和實(shí)際展示不一致,目測和style中的left屬性有關(guān)。

通過抓包分析以上請求中返回的info屬性,通過html格式化后,發(fā)現(xiàn)是多個(gè)td中包裹多個(gè)img標(biāo)簽,不過個(gè)數(shù)和展示的個(gè)數(shù)不一致,且src中的內(nèi)容是data:image/png;base64,開頭的圖片轉(zhuǎn)為base64形式。通過分析將對應(yīng)的圖片轉(zhuǎn)為數(shù)字字典如下

image_dict = {
    'data:image/png;base64,iVBORw0KGgoAAAANSUh...': 0,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAd...': 6,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAY...': 8,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAYAAAC...': 1,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQA...': 9,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAbC...': 4,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCA...': 2,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQA...': 3,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5...': 7,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAY...': 5
}

將格式化后的html中的base64圖片轉(zhuǎn)為數(shù)字

image-20210917164659843

對比得到兩個(gè)結(jié)論,首先class中去除一個(gè)加密字符串的屬性,且style中部分標(biāo)簽加上了display: none;屬性。說明拿到服務(wù)端返回結(jié)果后,js中為style加上了display為none的屬性。

全局搜索'display','none'或者'display', 'none'

image-20210917173431738

其中data.info就是獲取返回內(nèi)容中info的部分,也就是<td>標(biāo)簽里面的內(nèi)容,通過JQuery的選擇器,選擇標(biāo)簽中有number的元素,并將<td>標(biāo)簽的內(nèi)容添加進(jìn)去,通過獲取data中key和value中的值,并替換一些字符,最后經(jīng)過md5算法加密,得到一串密文,在密文前面加上一個(gè).,并賦值給變量j_key,通過選擇器,選擇有密文這個(gè)屬性的標(biāo)簽,并將其樣式設(shè)置成display:none,最終再刪除屬性中的密文

爬蟲

image_dict = {
    'data:image/png;base64,iVBORw0KGgoAAAANSUh...': 0,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAd...': 6,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAY...': 8,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAYAAAC...': 1,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQA...': 9,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAbC...': 4,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCA...': 2,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQA...': 3,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5...': 7,
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAY...': 5
}

answer_num_list = []


def get_base64_data(page_num):
    url = 'http://match.yuanrenxue.com/api/match/4?page={}'.format(page_num)
    headers = {
        'Host': 'match.yuanrenxue.com',
        'Pragma': 'no-cache',
        'Referer': 'http://match.yuanrenxue.com/match/4',
        'User-Agent': 'yuanrenxue.project',
        'X-Requested-With': 'XMLHttpRequest'
    }
    res = requests.get(url=url, headers=headers)
    # print(res.text)
    return res.json()['info'], res.json()['key'], res.json()['value']


def b642jpg(b64str, name):
    data = base64.b64decode(b64str)
    with open('{}.jpg'.format(name), 'wb') as f:
        f.write(data)
        print('打印完畢')


# var j_key = '.' + hex_md5(btoa(data.key + data.value).replace(/=/g, ''));
# 利用key和value計(jì)算出屬性為display=none的md5索引值
def get_j_key(key, value):
    return hashlib.md5(base64.b64encode((key + value).encode()).replace(b'=', b'')).hexdigest()


# 獲取td中4個(gè)圖片
def parse_every_group_nums(info_data):
    pattern = re.compile(r'<td>(.*?)</td>')
    every_group_nums_list = pattern.findall(info_data)
    return every_group_nums_list


# 利用j_key和每個(gè)圖片對應(yīng)的hash值,確定出要被用的所有數(shù)字子圖片,及其相對位置偏移值
def parse_real_use_num_info(every_group_nums, j_key):
    # 找到base64
    pattern = re.compile(r'img_number (.*?)"')
    img_number_list = pattern.findall(every_group_nums)
    # 找到圖片
    pattern = re.compile(r'base64,(.*?)"')
    ba64_str_list = pattern.findall(every_group_nums)
    # 找到樣式
    pattern = re.compile(r'style="(.*?)"')
    number_style_list = pattern.findall(every_group_nums)

    # 尋找所有要用的子圖
    ba64_str_list = [ba64_str_list[index] for index, img_number in enumerate(img_number_list) if img_number != j_key]
    num_list = [image_dict['data:image/png;base64,' + __] for __ in ba64_str_list]

    # 匹配每個(gè)子圖實(shí)際對應(yīng)的偏移量 6801 -> ['0', '11.5', '-11.5', '0.0']
    number_style_list = [number_style_list[index].replace('left:', '').replace('px', '') for index, img_number in
    enumerate(img_number_list) if img_number != j_key]

    # 根據(jù)偏移值,計(jì)算真實(shí)的數(shù)字順序
    ture_order_list = caculate_css_left(number_style_list, num_list)

    # 將每小組數(shù)字拼接并保存
    temp_num = 0
    for index, num in enumerate(ture_order_list[::-1]):
        temp_num += num * 10 ** index
    answer_num_list.append(temp_num)


# 根據(jù)圖片映射的數(shù)字和圖片的偏移值,計(jì)算出數(shù)字的真實(shí)順序,列表排序返回
def caculate_css_left(number_style_list, num_list):
    # [0, 1, -1, 0]
    number_style_list = [round(float(__) / 11) for __ in number_style_list]
    # 定義數(shù)組
    ture_order_list = ['']*len(number_style_list)
    for index, number_style in enumerate(number_style_list):
        ture_order_list[int(index + number_style)] = num_list[index]
    return ture_order_list


if __name__ == '__main__':
    # info, _, __ = get_base64_data(1)
    # # <td>有10組  left有63個(gè) display有0個(gè),需要md5計(jì)算進(jìn)行拼接base64  ed501a5e229d41330bee8399441bfbfb有39次  57feebf056bfb527e9ad8561e0694b0a有24次
    # '''
    # b642jpg(b64str, 'test')
    for page_num in range(1, 6):
        info_data, key, value = get_base64_data(page_num)
        j_key = get_j_key(key, value)
        every_group_nums_list = parse_every_group_nums(info_data)
        for every_group_nums in every_group_nums_list:
            parse_real_use_num_info(every_group_nums, j_key)
    print(sum(answer_num_list))

本文由博客群發(fā)一文多發(fā)等運(yùn)營工具平臺 OpenWrite 發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容