├── LibcSearcher.py ├── README.md └── setup.py /LibcSearcher.py: -------------------------------------------------------------------------------- 1 | import requests, json 2 | 3 | 4 | API_FIND = 'https://libc.rip/api/find' 5 | API_LIBC = 'https://libc.rip/api/libc/' 6 | HEADERS = {'Content-Type': 'application/json'} 7 | 8 | 9 | class LibcSearcher() : 10 | def __init__(self, symbol_name:str=None, address:int=None) : 11 | self.constraint = {} 12 | self.libc_list = [] 13 | self.the_libc = None 14 | 15 | if (symbol_name is not None) and (address is not None) : 16 | self.add_condition(symbol_name, address) 17 | 18 | 19 | def __len__(self) : 20 | self.pre_query_libc() 21 | if self.the_libc is None : 22 | return len(self.libc_list) 23 | else : 24 | return 1 25 | 26 | 27 | def __iter__(self) : 28 | self.pre_query_libc() 29 | if self.the_libc is None : 30 | return iter([ libc['id'] for libc in self.libc_list ]) 31 | else : 32 | return iter([ self.the_libc['id'] ]) 33 | 34 | 35 | def __bool__(self) : 36 | return (self.the_libc is not None) or (self.libc_list != []) 37 | 38 | 39 | def __repr__(self) : 40 | self.pre_query_libc() 41 | 42 | if self.libc_list == [] : 43 | return"\x1b[1;31m" + \ 44 | "[+] No libc satisfies constraints." + \ 45 | "\x1b[0m" 46 | 47 | elif self.the_libc is None : 48 | return "\x1b[33m" + \ 49 | "[+] Current constraints are not enough to determine a libc." + \ 50 | "\x1b[0m" 51 | else : 52 | return "[ libc_id ] : " + self.the_libc['id'] + "\n" \ 53 | "[ buildid ] : " + self.the_libc['buildid'] + "\n" \ 54 | "[ dowload ] : " + self.the_libc['download_url'] + "\n" \ 55 | "[ symbols ] : " + self.the_libc['symbols_url'] 56 | 57 | 58 | def add_condition(self, symbol_name:str, address:int) : 59 | self.constraint[symbol_name] = address 60 | self.libc_list = [] 61 | self.the_libc = None 62 | self.query_libc() 63 | 64 | 65 | def dump(self, symbol_name:str) -> int : 66 | self.pre_query_libc() 67 | if self.the_libc is None : 68 | self.determine_the_libc() 69 | return self.query_symbol(libc_id = self.the_libc['id'], symbol_name = symbol_name) 70 | 71 | 72 | def select_libc(self, chosen_index:int=0xDEADBEEF) : 73 | self.pre_query_libc() 74 | if chosen_index == 0xDEADBEEF : 75 | for index, libc in enumerate(self.libc_list) : 76 | print(str(index) + " - " + libc['id']) 77 | chosen_index = input("\x1b[33m" + 78 | "[+] Choose one : " + 79 | "\x1b[0m") 80 | try : 81 | self.the_libc = self.libc_list[int(chosen_index)] 82 | except IndexError : 83 | print("\x1b[1;31m" + 84 | "[+] Index out of bound!" + 85 | "\x1b[0;m") 86 | self.select_libc() 87 | 88 | 89 | def pre_query_libc(self) : 90 | if self.libc_list == [] : 91 | self.query_libc() 92 | 93 | 94 | def determine_the_libc(self) : 95 | if self.libc_list == [] : 96 | print("\x1b[1;31m" + 97 | "[+] No libc satisfies constraints." + 98 | "\x1b[0m") 99 | exit() 100 | 101 | elif len(self.libc_list) == 1 : 102 | self.the_libc = self.libc_list[0] 103 | 104 | else : 105 | print("\x1b[33m" + 106 | "[+] There are multiple libc that meet current constraints :" + 107 | "\x1b[0m") 108 | self.select_libc() 109 | 110 | 111 | def query_libc(self) : 112 | payload = { 113 | "symbols" : 114 | { s_name: hex(s_addr) for s_name, s_addr in self.constraint.items() } 115 | } 116 | result = requests.post(API_FIND, data=json.dumps(payload), headers=HEADERS) 117 | self.libc_list = json.loads(result.text) 118 | 119 | if len(self.libc_list) == 1 : 120 | self.the_libc = self.libc_list[0] 121 | 122 | 123 | def query_symbol(self, libc_id:str, symbol_name:str) -> int : 124 | payload = { 125 | "symbols": 126 | [ symbol_name ] 127 | } 128 | result = requests.post(API_LIBC+libc_id, data=json.dumps(payload), headers=HEADERS) 129 | return int(json.loads(result.text)['symbols'][symbol_name], 16) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibcSearcher-ng 2 |
3 | 4 | ## Introduction 5 | 6 | - 这里是全新的 LibcSearcher 实现。基于 [libc-database](https://github.com/niklasb/libc-database) 云端数据库而非本地数据库。 7 | - [原版 LibcSearcher 仓库](https://github.com/lieanu/LibcSearcher)由于年久失修,经测试发现其基本失效。 8 | - 选择新建一个项目而非基于原有 LibcSearcher 继续开发的原因如下: 9 | - 原仓库基于 libc-database ,拷贝其数据库中的部分常用 libc 文件,在本地进行求解。这一方案有两个问题: 10 | - libc 库不完整,仅包含了常用 libc 文件。若下载整个数据库则磁盘占用和下载成本过大。 11 | - 上游数据库更新时不方便及时获悉,且需要手动更新本地数据库。 12 | - libc-database 现已提供 web-api,可直接向其服务发起请求获取查询结果,解决了上述两个问题。 13 | - 同时为了确保 CTFer 们以前的 exp 的可用性,LibcSearcher-ng 将以与原 LibcSearcher 完全相同的接口来构建。 14 | - 比起原版 LibcSearcher 只多了一个缺点:断网就不可用了。🤣 15 | - 若需要基于本地数据库的~~可以抵御断网攻击的~~ LibcSearcher,github 上已有其它维护了相应实现的仓库。 16 | 17 | > 目前发现libc-database所提供的服务器能承受的负载不高,有时会出现服务挂掉的情况(可能是难以处理国内的比赛期间大量的请求)。不过上次挂掉后niklasb说会考虑升级服务器。 18 | 19 | > 可以使用如下命令直接测试服务器是否正常: 20 | 21 | `curl -X POST -H 'Content-Type: application/json' --data '{"symbols": ["strcat"]}' 'https://libc.rip/api/libc/libc6_2.27-3ubuntu1.2_amd64'` 22 | 23 | 24 |
25 | 26 | ## Installation 27 | 28 | #### 使用 pip 29 | 30 | ```shell 31 | pip3 install LibcSearcher 32 | ``` 33 | 34 | 更新 35 | 36 | ```shell 37 | pip3 install -U LibcSearcher 38 | ``` 39 | 40 | #### 使用本仓库 41 | 42 | ```shell 43 | git clone https://github.com/dev2ero/LibcSearcher.git 44 | cd LibcSearcher 45 | python3 setup.py develop 46 | ``` 47 | 48 | > 如要更新,只需拉取最新代码后,重新在仓库目录内执行 `python3 setup.py develop` 49 | 50 |
51 | 52 | ## Usage 53 | 54 | ```python 55 | from LibcSearcher import * 56 | obj = LibcSearcher("fgets", 0x7ff39014bd90) # 使用一个已知符号地址作为初始约束,初始化 LibcSearcher 57 | obj.add_condition("atoi", 218528) # 添加一个约束条件 58 | obj.dump("printf") # 根据已有约束条件,查询某个符号在 Libc 中的地址 59 | ``` 60 | 61 | > 此外,比起以上原版接口,添加了如下些许姿势 62 | 63 | ```python 64 | len(obj) # 返回在当前约束条件下,可能的 Libc 数量 65 | 66 | print(obj) # 若 Libc 已被唯一确定,打印其详细信息 67 | 68 | for libc in obj : 69 | print(libc) # 实现了迭代器,打印(或其它操作)当前所有可能的 Libc 70 | 71 | obj.select_libc() # 打印可能的 Libc 列表,手动选择一个认为正确的 Libc 72 | obj.select_libc(2) # 手动选择 2 号 Libc 作为正确的 Libc 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | from os import path as os_path 3 | 4 | this_directory = os_path.abspath(os_path.dirname(__file__)) 5 | 6 | def read_file(filename): 7 | with open(os_path.join(this_directory, filename), encoding='utf-8') as f: 8 | long_description = f.read() 9 | return long_description 10 | 11 | setup( 12 | name="LibcSearcher", 13 | version="1.1.5", 14 | description="Python wrapper for libc-database.", 15 | author="IZAY01", 16 | author_email="IZAYOInt0x80@gmail.com", 17 | platforms=["any"], 18 | license="BSD", 19 | url="https://github.com/IZAY01/LibcSearcher", 20 | long_description=read_file('README.md'), 21 | long_description_content_type="text/markdown", 22 | install_requires=[ 23 | 'requests', 24 | ], 25 | packages=find_packages(), ) 26 | --------------------------------------------------------------------------------