summaryrefslogtreecommitdiff
path: root/3/10_control_and_data
diff options
context:
space:
mode:
Diffstat (limited to '3/10_control_and_data')
-rw-r--r--3/10_control_and_data/00_prog.c0
-rw-r--r--3/10_control_and_data/01_echo.c24
-rw-r--r--3/10_control_and_data/46_get_line.c31
-rw-r--r--3/10_control_and_data/47_address_range.c10
-rw-r--r--3/10_control_and_data/48_stack_protection.c52
-rw-r--r--3/10_control_and_data/49_variable_stack.c81
6 files changed, 198 insertions, 0 deletions
diff --git a/3/10_control_and_data/00_prog.c b/3/10_control_and_data/00_prog.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/3/10_control_and_data/00_prog.c
diff --git a/3/10_control_and_data/01_echo.c b/3/10_control_and_data/01_echo.c
new file mode 100644
index 0000000..8ef71e2
--- /dev/null
+++ b/3/10_control_and_data/01_echo.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+char* gets(char *s) {
+ int c;
+ char *dest = s;
+ while ((c = getchar()) != '\n' && c != EOF) {
+ *dest++ = c;
+ }
+ if ( c == EOF && dest == s) {
+ return NULL;
+ }
+ *dest++ = '\0';
+ return s;
+}
+
+void echo() {
+ char buf[8];
+ gets(buf);
+ puts(buf);
+}
+
+int main(void) {
+ echo();
+}
diff --git a/3/10_control_and_data/46_get_line.c b/3/10_control_and_data/46_get_line.c
new file mode 100644
index 0000000..f1920e8
--- /dev/null
+++ b/3/10_control_and_data/46_get_line.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// char *get_line()
+// 400720: 53 push %rbx
+// 400721: 48 83 ec 10 sub $0x10,%rsp
+// 400725: 48 89 e7 mov %rsp,%rdi
+// 400728 e8 73 ff ff ff callq 4006a0 <gets>
+char *get_line() {
+ char buf[4];
+ char *result;
+ gets(buf);
+ result = malloc(strlen(buf));
+ strcpy(result, buf);
+ return result;
+}
+int main(void) {
+ printf("%s\n", get_line());
+}
+// A. B. (I mistakingly thought $0x10 was the same as $10...)
+// 00 34 33 32 31 30 39 38 return address
+// 37 36 35 34 33 32 31 30 callee saved %rbx
+// 39 38 37 36 35 34 33 32< sub $rsp - 8
+// 31 30 00 00 00 00 00 40 sub $rsp -16
+// 07 32< return address gets
+//
+// C. 00 34 33 32 31 30 39 38
+// D. %rbx
+// E. Malloc should consider the terminating null (strlen+1) and check for NULL pointer result
diff --git a/3/10_control_and_data/47_address_range.c b/3/10_control_and_data/47_address_range.c
new file mode 100644
index 0000000..57a3fcb
--- /dev/null
+++ b/3/10_control_and_data/47_address_range.c
@@ -0,0 +1,10 @@
+//
+// A. Using bc
+//
+ibase=16; FFFFB754
+ibase=16; FFFFD754 - FFFFB754
+8192
+2^13
+// B.
+2^5
+32
diff --git a/3/10_control_and_data/48_stack_protection.c b/3/10_control_and_data/48_stack_protection.c
new file mode 100644
index 0000000..08cb4e8
--- /dev/null
+++ b/3/10_control_and_data/48_stack_protection.c
@@ -0,0 +1,52 @@
+int len(char *s) {
+ return strlen(s);
+}
+
+void iptoa(char *s, long *p) {
+ long val = *p;
+ sprintf(s, "%ld", val);
+}
+
+// int inlen(long x)
+// x in %rdi
+// without canary
+//
+// intlen:
+// subq $40, %rsp allocate 5*8 bytes
+// movq %rdi, 24(%rsp) put x on the stack
+// leaq 24(%rsp), %rsi set &v = &x to the second argument
+// movq %rsp, %rdi set buf[12] to %rsp
+// call iptoa
+//
+// 0<rsp+32 <-?
+// 0<rsp+24 <-v
+// 0<rsp+16 <-?
+// 0<rsp+8 <-buf[12]
+// 0<rsp <-buf[12]
+//
+// with canary
+//
+// intlen:
+// subq $56, %rsp
+// movq %fs:40, %rax
+// movq %rax, 40(%rsp)
+// xorl %eax, %eax
+// movq %rdi, 8(%rsp)
+// leaq 8(%rsp), %rsi
+// leaq 16(%rsp), %rdi
+// call iptoa
+//
+// 0<rsp+48 <-
+// 0<rsp+40 <-canary
+// 0<rsp+32 <-
+// 0<rsp+24 <-
+// 0<rsp+16 <-buf[12]
+// 0<rsp+8 <-v
+// 0<rsp <-
+int intlen(long x) {
+ long v;
+ char buf[12];
+ v = x;
+ iptoa(buf, &v);
+ return len(buf);
+}
diff --git a/3/10_control_and_data/49_variable_stack.c b/3/10_control_and_data/49_variable_stack.c
new file mode 100644
index 0000000..d72c235
--- /dev/null
+++ b/3/10_control_and_data/49_variable_stack.c
@@ -0,0 +1,81 @@
+// A.
+// vframe:
+// pushq %rbp
+// movq %rsp, %rbp
+// subq $16, %rsp
+// leaq 22(,%rdi,8), %rax
+// andq $-16, %rax
+//
+//
+// bitlevel representation of -16
+// 1111111111111111111111111111111111111111111111111111111111110000
+//
+// rax
+// 22 + n*8
+// n=0 0000000000000000000000000000000000000000000000000000000000010110 22
+// n=1 0000000000000000000000000000000000000000000000000000000000011110 30
+// n=2 0000000000000000000000000000000000000000000000000000000000100110 38
+// n=3 0000000000000000000000000000000000000000000000000000000000101110 46
+// n=4 0000000000000000000000000000000000000000000000000000000000110110 54
+// n=5 0000000000000000000000000000000000000000000000000000000000111110 62
+//
+// (22 + n*8) & -16
+// n=0 0000000000000000000000000000000000000000000000000000000000010000 16 8n+16
+// n=1 0000000000000000000000000000000000000000000000000000000000010000 16 8n+8
+// n=2 0000000000000000000000000000000000000000000000000000000000100000 32 8n+16
+// n=3 0000000000000000000000000000000000000000000000000000000000100000 32 8n+8
+// n=4 0000000000000000000000000000000000000000000000000000000000110000 48
+// n=5 0000000000000000000000000000000000000000000000000000000000110000 48
+//
+// print("{:064b}".format((0*8+22) & -16))
+// print("{:064b}".format((1*8+22) & -16))
+// print("{:064b}".format((2*8+22) & -16))
+// print("{:064b}".format((3*8+22) & -16))
+// print("{:064b}".format((4*8+22) & -16))
+// print("{:064b}".format((5*8+22) & -16))
+//
+// B.
+// vframe:
+// pushq %rbp
+// movq %rsp, %rbp
+// subq $16, %rsp
+// leaq 22(,%rdi,8), %rax
+// andq $-16, %rax
+//
+// subq %rax, %rsp
+//
+// leaq 7(%rsp), %rax rax <- (rsp+7) = (rsp+(n-1)), n = 8
+// shrq $3, %rax rax <- (floor(rax/8))
+// leaq 0(,%rax,8), %r8 r8 <- ceil(rsp/8)*8
+//
+// Important We are growing the stack downwards.
+// But the array index grows upwards.
+//
+// See 2.3.7 for derivation.
+// If x%(1<<k) == 0 then the bias has no effect, rounding down does not happen, there is no fraction.
+// else
+// Since the operation of adding the bias and then flooring happens,
+// this results in rounding towards zero, or taking the ceiling.
+//
+// So if rsp was a multiple of 8 then nothing happens.
+// Otherwise the start of the array is set to the first multiple of 8 towards the bottom of the stack (ceil goes towards greater addresses of the bottom).
+//
+// C.
+//
+// s_2 = (- s_1
+// (+ (if (odd? n) 8 16) (* n 8) )
+// )
+//
+// p = ceil(s2/8)*8
+// e2 = (- p s2)
+// e1 = (- s2 s1 e2 8n)
+//
+// 2065 - (8+5*8)
+//
+// n s_1 s_2 p e_1 e_2
+// 5 2065 2017 2024 1 7
+// 6 2064 2000 2000 16 0
+//
+// D.
+// p is 8byte aligned owing to the 8-10 instructions.
+// s2 is not guaranteed to be aligned, so 1 byte. (But all we are doing is subtracting multiples of 16 from s1... not sure how this helps)