├── .gitignore ├── LICENSE ├── README.md ├── final.c ├── http.c ├── myhttp.s ├── printf-example.c ├── printf-hello.c ├── run-finalizer.c └── webserver.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | 5 | # Libraries 6 | *.lib 7 | *.a 8 | 9 | # Shared objects (inc. Windows DLLs) 10 | *.dll 11 | *.so 12 | *.so.* 13 | *.dylib 14 | 15 | # Executables 16 | *.exe 17 | *.out 18 | *.app 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Yohanes Nugroho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | printf-webserver 2 | ================ 3 | 4 | Implementing a web server in a single printf() call 5 | 6 | You can read more about this [in this post](http://tinyhack.com/?p=280) 7 | -------------------------------------------------------------------------------- /final.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | printf("%*c%hn%*c%hn" 6 | "\xeb\x3d\x48\x54\x54\x50\x2f\x31\x2e\x30\x20\x32" 7 | "\x30\x30\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d" 8 | "\x74\x79\x70\x65\x3a\x74\x65\x78\x74\x2f\x68\x74" 9 | "\x6d\x6c\x0d\x0a\x0d\x0a\x3c\x68\x31\x3e\x48\x65" 10 | "\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x3c\x2f" 11 | "\x68\x31\x3e\x4c\x8d\x2d\xbc\xff\xff\xff\x48\x89" 12 | "\xe3\x48\x83\xeb\x10\x48\x31\xc0\x50\x66\xb8\x1f" 13 | "\x90\xc1\xe0\x10\xb0\x02\x50\x31\xd2\x31\xf6\xff" 14 | "\xc6\x89\xf7\xff\xc7\x31\xc0\xb0\x29\x0f\x05\x49" 15 | "\x89\xc2\x31\xd2\xb2\x10\x48\x89\xde\x89\xc7\x31" 16 | "\xc0\xb0\x31\x0f\x05\x31\xc0\xb0\x05\x89\xc6\x4c" 17 | "\x89\xd0\x89\xc7\x31\xc0\xb0\x32\x0f\x05\x31\xd2" 18 | "\x31\xf6\x4c\x89\xd0\x89\xc7\x31\xc0\xb0\x2b\x0f" 19 | "\x05\x49\x89\xc4\x48\x31\xd2\xb2\x3d\x4c\x89\xee" 20 | "\x4c\x89\xe7\x31\xc0\xff\xc0\x0f\x05\x31\xf6\xff" 21 | "\xc6\xff\xc6\x4c\x89\xe7\x31\xc0\xb0\x30\x0f\x05" 22 | "\x4c\x89\xe7\x31\xc0\xb0\x03\x0f\x05\xeb\xc3", 23 | ((((unsigned long int)0x4005c8 + 12) >> 16) & 0xffff), 24 | 0, 0x00000000006007D8 + 2, 25 | (((unsigned long int)0x4005c8 + 12) & 0xffff)- 26 | ((((unsigned long int)0x4005c8 + 12) >> 16) & 0xffff), 27 | 0, 0x00000000006007D8 ); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /http.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 16 | struct sockaddr_in serv_addr; 17 | bzero((char *)&serv_addr, sizeof(serv_addr)); 18 | serv_addr.sin_family = AF_INET; 19 | serv_addr.sin_addr.s_addr = INADDR_ANY; 20 | serv_addr.sin_port = htons(8080); 21 | bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 22 | listen(sockfd, 5); 23 | while (1) { 24 | int cfd = accept(sockfd, 0, 0); 25 | char *s = "HTTP/1.0 200\r\nContent-type:text/html\r\n\r\n

Hello world!

"; 26 | if (fork()==0) { 27 | write(cfd, s, strlen(s)); 28 | shutdown(cfd, SHUT_RDWR); 29 | close(cfd); 30 | } 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /myhttp.s: -------------------------------------------------------------------------------- 1 | .file "min.c" 2 | .text 3 | .globl main 4 | .type main, @function 5 | main: 6 | 7 | jmp .L0 8 | .msg: 9 | .ascii "HTTP/1.0 200\r\nContent-type:text/html\r\n\r\n

Hello World!

" 10 | .L0: 11 | lea .msg(%rip), %r13 12 | .LFB0: 13 | // used for parameter passing: %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used 14 | // create this data on stack 15 | // 0x02,0x00,0x1f,0x90, 0x00,0x00,0x00,0x00, 16 | // 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 17 | // --- 18 | 19 | movq %rsp, %rbx 20 | sub $16, %rbx 21 | xorq %rax, %rax 22 | pushq %rax 23 | //movq $0x901f0002, %rax 24 | movw $0x901f, %ax 25 | shl $16, %eax 26 | movb $2, %al 27 | pushq %rax 28 | xorl %edx, %edx 29 | xorl %esi, %esi 30 | //set esi to 1 31 | inc %esi 32 | mov %esi, %edi 33 | //set edi to 2 34 | inc %edi 35 | xorl %eax, %eax 36 | movb $0x29, %al 37 | syscall 38 | mov %rax, %r10 39 | //call bind 40 | //movl $16, %edx 41 | xorl %edx, %edx 42 | movb $16, %dl 43 | movq %rbx, %rsi 44 | movl %eax, %edi 45 | xorl %eax, %eax 46 | movb $0x31, %al 47 | syscall 48 | //call listen 49 | xorl %eax, %eax 50 | movb $5, %al 51 | movl %eax, %esi 52 | mov %r10, %rax 53 | movl %eax, %edi 54 | xorl %eax, %eax 55 | movb $0x32, %al 56 | syscall 57 | .L1: 58 | //call accept 59 | xorl %edx, %edx 60 | xorl %esi, %esi 61 | mov %r10, %rax 62 | movl %eax, %edi 63 | xorl %eax, %eax 64 | movb $0x2b, %al 65 | syscall 66 | mov %rax, %r12 67 | //r12 is the client fd 68 | //fork 69 | // xorl %eax, %eax 70 | // movb $0x39, %al 71 | // syscall 72 | // testl %eax, %eax 73 | // jne .L1 74 | //write 75 | xorq %rdx, %rdx 76 | //is string length 77 | mov $61,%dl 78 | mov %r13, %rsi 79 | mov %r12, %rdi 80 | //eax was 0 because of fork 81 | xorl %eax, %eax 82 | inc %eax 83 | syscall 84 | //shutdown 85 | xorl %esi, %esi 86 | inc %esi 87 | inc %esi 88 | // movl $2, %esi 89 | movq %r12, %rdi 90 | xorl %eax, %eax 91 | movb $0x30, %al 92 | syscall 93 | //close 94 | movq %r12, %rdi 95 | xorl %eax, %eax 96 | movb $0x3, %al 97 | syscall 98 | 99 | jmp .L1 100 | ret 101 | 102 | .LFE0: 103 | .size main, .-main 104 | .ident "GCC: (Debian 4.8.2-16) 4.8.2" 105 | .section .note.GNU-stack,"",@progbits 106 | -------------------------------------------------------------------------------- /printf-example.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(){ 3 | int count; 4 | printf("AB%n", &count); 5 | printf("\n%d characters printed\n", count); 6 | } 7 | -------------------------------------------------------------------------------- /printf-hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define FUNCTION_ADDR ((uint64_t)hello) 6 | #define DESTADDR 0x0000000000600948 7 | 8 | void hello() 9 | { 10 | printf("\n\n\n\nhello world\n\n"); 11 | } 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | short a= FUNCTION_ADDR & 0xffff; 16 | short b = (FUNCTION_ADDR >> 16) & 0xffff; 17 | printf("a = %04x b = %04x\n", a, b);fflush(stdout); 18 | uint64_t *p = (uint64_t*)DESTADDR; 19 | printf("before: %08lx\n", *p); fflush(stdout); 20 | printf("%*c%hn", b, 0, DESTADDR + 2 );fflush(stdout); 21 | printf("after1: %08lx\n", *p); fflush(stdout); 22 | printf("%*c%hn", a, 0, DESTADDR);fflush(stdout); 23 | printf("after2: %08lx\n", *p); fflush(stdout); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /run-finalizer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ADDR 0x00000000600720 5 | 6 | void hello() 7 | { 8 | printf("hello world\n"); 9 | } 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | (*((unsigned long int*)ADDR))= (unsigned long int)hello; 14 | } 15 | -------------------------------------------------------------------------------- /webserver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define FUNCTION_ADDR ((uint64_t)0x4005c8 + 12) 6 | #define DESTADDR 0x00000000006007D8 7 | #define a (FUNCTION_ADDR & 0xffff) 8 | #define b ((FUNCTION_ADDR >> 16) & 0xffff) 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | printf("%*c%hn%*c%hn" 13 | "\xeb\x3d\x48\x54\x54\x50\x2f\x31\x2e\x30\x20\x32" 14 | "\x30\x30\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d" 15 | "\x74\x79\x70\x65\x3a\x74\x65\x78\x74\x2f\x68\x74" 16 | "\x6d\x6c\x0d\x0a\x0d\x0a\x3c\x68\x31\x3e\x48\x65" 17 | "\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x3c\x2f" 18 | "\x68\x31\x3e\x4c\x8d\x2d\xbc\xff\xff\xff\x48\x89" 19 | "\xe3\x48\x83\xeb\x10\x48\x31\xc0\x50\x66\xb8\x1f" 20 | "\x90\xc1\xe0\x10\xb0\x02\x50\x31\xd2\x31\xf6\xff" 21 | "\xc6\x89\xf7\xff\xc7\x31\xc0\xb0\x29\x0f\x05\x49" 22 | "\x89\xc2\x31\xd2\xb2\x10\x48\x89\xde\x89\xc7\x31" 23 | "\xc0\xb0\x31\x0f\x05\x31\xc0\xb0\x05\x89\xc6\x4c" 24 | "\x89\xd0\x89\xc7\x31\xc0\xb0\x32\x0f\x05\x31\xd2" 25 | "\x31\xf6\x4c\x89\xd0\x89\xc7\x31\xc0\xb0\x2b\x0f" 26 | "\x05\x49\x89\xc4\x48\x31\xd2\xb2\x3d\x4c\x89\xee" 27 | "\x4c\x89\xe7\x31\xc0\xff\xc0\x0f\x05\x31\xf6\xff" 28 | "\xc6\xff\xc6\x4c\x89\xe7\x31\xc0\xb0\x30\x0f\x05" 29 | "\x4c\x89\xe7\x31\xc0\xb0\x03\x0f\x05\xeb\xc3" 30 | , b, 0, DESTADDR + 2, a-b, 0, DESTADDR ); 31 | } 32 | --------------------------------------------------------------------------------