├── 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 |
--------------------------------------------------------------------------------