Skip to content

Instantly share code, notes, and snippets.

@FedericoHeichou
Last active November 16, 2025 20:13
Show Gist options
  • Select an option

  • Save FedericoHeichou/ffb843f02331b47280154d43d257920e to your computer and use it in GitHub Desktop.

Select an option

Save FedericoHeichou/ffb843f02331b47280154d43d257920e to your computer and use it in GitHub Desktop.
Today I fucked up really hard with pam and the damn gkm changed the keyring password with the same password but adding a "\n" at the end, logging "fixed login keyring password to match login password".
import socket
import os
'''
Today I fucked up really hard with pam and the damn gkm changed the keyring password with the same password but adding a "\n" at the end, logging "fixed login keyring password to match login password".
Obviously at first I tried unlocking it via command line (using gnome-keyring-daemon --unlock) adding the "\n" to the password, but it didn't work.
So I went in a rabbit hole trying to find the correct password.
After some tries I decided to send the raw password (with "\n" at the end) to the socket itself, and it worked.
Now the problem is that I can't type the "\n" in the gnome-keyring prompt, so I had to send the change password operation to the socket as well.
After some tries I managed to change the password back to the original one without the "\n" at the end.
'''
# If you may need the source code to reverse things
# apt source libpam-gnome-keyring -> gnome-keyring-46.1/daemon/control/gkd-control-server.c
# Run manually the keyring daemon
# gnome-keyring-daemon -r -f --components=secrets
OPERATION_VERIFY_PASSWORD = 1
OPERATION_CHANGE_PASSWORD = 2
socket_path = '/run/user/1000/keyring/control'
def main():
if not os.path.exists(socket_path):
print(f'Socket path does not exist: {socket_path}')
return
password = b'YourBrokenPassword!\n' # <- god damn it, it ends with a newline!
new_password = password[:-1]
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client_socket:
try:
client_socket.connect(socket_path)
# message -> null byte + header + command + args
# header -> total size (4 bytes) + command (4 bytes)
# args -> password length (4 bytes) + password
args = len(password).to_bytes(4, byteorder='big') + password
op = OPERATION_VERIFY_PASSWORD.to_bytes(4, byteorder='big')
header = (4 + len(op) + len(args)).to_bytes(4, byteorder='big')
message = b'\0' + header + op + args
print('Sending:', message)
client_socket.sendall(message)
response = client_socket.recv(1024)
print(f'Received: {response}')
if response.endswith(b'\0'):
print('SUCCESS!!!!', password)
except socket.error as e:
print(f'Errore nella connessione: {e}')
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client_socket:
try:
client_socket.connect(socket_path)
# message -> null byte + header + command + args
# header -> total size (4 bytes) + command (4 bytes)
# args -> password length (4 bytes) + password + new password length (4 bytes) + new password
args = (len(password).to_bytes(4, byteorder='big') + password +
len(new_password).to_bytes(4, byteorder='big') + new_password)
op = OPERATION_CHANGE_PASSWORD.to_bytes(4, byteorder='big')
header = (4 + len(op) + len(args)).to_bytes(4, byteorder='big')
message = b'\0' + header + op + args
print('Sending:', message)
client_socket.sendall(message)
response = client_socket.recv(1024)
print(f'Received: {response}')
if response.endswith(b'\0'):
print('PASSWORD CHANGED SUCCESSFULLY!!!!', new_password)
except socket.error as e:
print(f'Errore nella connessione: {e}')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment