Last active
November 16, 2025 20:13
-
-
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".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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