Last active
December 10, 2020 18:57
-
-
Save dbwodlf3/82bf2f98d6eb2c21fc327839f5f53625 to your computer and use it in GitHub Desktop.
SMC_IN_LL.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| =============================================================================== | |
| SMC Codes in C -> ll | |
| =============================================================================== | |
| C언어에서 작성한 SMC 코드가, LL 파일에서 나타나는 형태에 대하여 말한다. | |
| =============================================================================== | |
| 1. 코드 영역을 직접 수정하는 경우 | |
| =============================================================================== | |
| 1.1. PIE SMC 코드 | |
| C언어에서 .text 영역 다음에 .data 영역이 오므로, offset이 function인 경우 양수이고 | |
| global var인 경우에 음수가 된다. Example 1과 Example 2을 통해 확인할 수 있다. | |
| 1.2. NO-PIE SMC 코드 | |
| PIE SMC 코드와는 다르게 inttoptr 명령어를 사용하여 바로 direct 하게 꽂아 넣는 것을 | |
| 확인할 수 있다. 지역 변수를 사용한다고 하더라도 그 의미는 크게 변하지 않는다. | |
| Example 3과 Example 4를 통해 확인할 수 있다. | |
| =============================================================================== | |
| 2. Data 영역으로 실행 흐름이 넘어가는 경우. | |
| =============================================================================== | |
| 2.1. 실행될 Code가 global scope에 있는 경우. | |
| .text 영역 다음에 있는 .data 영역에 code가 존재하므로, 이 코드 또한 PIE SMC 코드다. | |
| 해당 code가 literal 하게 선언이 되어 있는 경우와, 나중에 초기화 되는 경우가 있지만 | |
| 함수포인터를 이용하여 해당 코드를 실행할 때의 명령어는 동일 하다. | |
| Example 5.와 Example 6. 에서 확인할 수 있다. | |
| 2.2. 실행될 Code가 local scope에 있는 경우 | |
| PIE이나 NO-PIE에 상관없이 stack 은 고정되어 있으므로 이 경우 또한 PIE SMC 코드다. | |
| 해당 coder가 literal 하게 선언이 되어 있는 경우와, 나중에 초기화 되는 경우가 있지만 | |
| 함수포인터를 이용하여 해당 코드를 실행할 때의 명령어는 동일하다. | |
| Example 7과 Exmaple 8에서 확인할 수 있다. | |
| =============================================================================== | |
| Examples | |
| =============================================================================== | |
| Example 1. | |
| smc17.c & clang_m64_smc17.ll : offset이 function인 경우. | |
| ------------------------------------------------------------------------------- | |
| int main(){ | |
| unsigned char *write_address = (unsigned char *)main + 107; | |
| *write_address = 0x90; | |
| return 0; | |
| } | |
| => | |
| define dso_local i32 @main() #0 { | |
| ... | |
| %2 = alloca i8*, align 8 | |
| store i8* getelementptr inbounds (i8, i8* bitcast (i32 ()* @main to i8*), i64 107), i8** %2, align 8 | |
| %3 = load i8*, i8** %2, align 8 | |
| store i8 -112, i8* %3, align 1 | |
| ret i32 0 | |
| } | |
| =============================================================================== | |
| Example 2. | |
| smc16.c & clang_m64_smc16.ll : offset이 global var인 경우. | |
| ------------------------------------------------------------------------------- | |
| unsigned long long key; | |
| int main(){ | |
| unsigned long long *key_address = (void*) &key-0x200999; | |
| *key_address = 0x9090909090909090; | |
| ... | |
| } | |
| => | |
| @key = common dso_local global i64 0, align 8 | |
| define dso_local i32 @main() #0 { | |
| ... | |
| %2 = alloca i64*, align 8 | |
| store i64* bitcast (i8* getelementptr (i8, i8* bitcast (i64* @key to i8*), i64 -2099609) to i64*), i64** %2, align 8 | |
| %4 = load i64*, i64** %2, align 8 | |
| store i64 -8029759185026510704, i64* %4, align 8 | |
| ... | |
| } | |
| =============================================================================== | |
| Example 3. | |
| smc14.c && clang_m64_smc14.ll : 로컬 변수를 사용하지 않고 바로 쓰는 경우. | |
| ------------------------------------------------------------------------------- | |
| int main(){ | |
| ... | |
| *(unsigned long long*)0x40051c = 0x9090909090909090; | |
| ... | |
| } | |
| => | |
| define dso_local i32 @main() #0 { | |
| ... | |
| store i64 -8029759185026510704, i64* inttoptr (i64 4195612 to i64*), align 8 | |
| ... | |
| } | |
| =============================================================================== | |
| Example 4. | |
| smc15.c && clang_m64_smc15.ll : 로컬 변수를 사용하여 쓰는 경우. | |
| ------------------------------------------------------------------------------- | |
| int main(){ | |
| unsigned long long *memory_ptr = (unsigned long long*)0x400527; | |
| ... | |
| *memory_ptr = 0x9090909090909090; | |
| ... | |
| } | |
| => | |
| define dso_local i32 @main() #0 { | |
| ... | |
| %2 = alloca i64*, align 8 | |
| store i64* inttoptr (i64 4195623 to i64*), i64** %2, align 8 | |
| %4 = load i64*, i64** %2, align 8 | |
| store i64 -8029759185026510704, i64* %4, align 8 | |
| ... | |
| } | |
| =============================================================================== | |
| Example 5. | |
| smc12.c && clang_m64_smc12.ll : code가 global scope인 경우. | |
| ------------------------------------------------------------------------------- | |
| char code[] = | |
| "\xb8\x01\x00\x00\x00" | |
| "\xcd\x80"; | |
| int main(){ | |
| ... | |
| ((void(*)())code)(); | |
| ... | |
| } | |
| => | |
| @code = dso_local global [8 x i8] c"\B8\01\00\00\00\CD\80\00", align 1 | |
| ... | |
| define dso_local i32 @main() #0 { | |
| ... | |
| call void (...) bitcast ([8 x i8]* @code to void (...)*)() | |
| ... | |
| } | |
| =============================================================================== | |
| Example 6. | |
| smc19.c && clang_m64_smc19.ll : code가 global scope이고, 동적으로 쓰이는 경우 | |
| ------------------------------------------------------------------------------- | |
| char code[8]; | |
| int main(){ | |
| code[0] = '\xb8'; | |
| code[1] = '\x01'; | |
| code[2] = '\x00'; | |
| code[3] = '\x00'; | |
| code[4] = '\x00'; | |
| code[5] = '\xcd'; | |
| code[6] = '\x80'; | |
| code[7] = '\x00'; | |
| ... | |
| ((void(*)())code)(); | |
| ... | |
| } | |
| => | |
| @code = dso_local global [8 x i8] c"\B8\01\00\00\00\CD\80\00", align 1 | |
| ... | |
| define dso_local i32 @main() #0 { | |
| ... | |
| store i8 -72, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 0), align 1 | |
| store i8 1, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 1), align 1 | |
| store i8 0, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 2), align 1 | |
| store i8 0, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 3), align 1 | |
| store i8 0, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 4), align 1 | |
| store i8 -51, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 5), align 1 | |
| store i8 -128, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 6), align 1 | |
| store i8 0, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @code, i64 0, i64 7), align 1 | |
| ... | |
| call void (...) bitcast ([8 x i8]* @code to void (...)*)() | |
| ... | |
| } | |
| =============================================================================== | |
| Example 7. | |
| smc13.c && clang_m64_smc13.ll : code가 function scope인 경우. | |
| ------------------------------------------------------------------------------- | |
| int main(){ | |
| char code[] = | |
| "\xb8\x01\x00\x00\x00" | |
| "\xcd\x80"; | |
| ... | |
| ((void(*)())code)(); | |
| ... | |
| } | |
| => | |
| @__const.main.code = private unnamed_addr constant [8 x i8] c"\B8\01\00\00\00\CD\80\00", align 1 | |
| ... | |
| define dso_local i32 @main() #0 { | |
| ... | |
| %2 = alloca [8 x i8], align 1 | |
| %3 = bitcast [8 x i8]* %2 to i8* | |
| call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %3, i8* align 1 getelementptr inbounds ([8 x i8], [8 x i8]* @__const.main.code, i32 0, i32 0), i64 8, i1 false) | |
| ... | |
| %6 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 0 | |
| %7 = bitcast i8* %6 to void (...)* | |
| call void (...) %7() | |
| ... | |
| } | |
| =============================================================================== | |
| Example 8. | |
| smc18.c && clang_m64_smc18.ll : code가 function scope이고 동적으로 쓰이는 경우. | |
| ------------------------------------------------------------------------------- | |
| int main(){ | |
| char code[8]; | |
| ... | |
| code[0] = '\xb8'; | |
| code[1] = '\x01'; | |
| code[2] = '\x00'; | |
| code[3] = '\x00'; | |
| code[4] = '\x00'; | |
| code[5] = '\xcd'; | |
| code[6] = '\x80'; | |
| code[7] = '\x00'; | |
| ... | |
| ((void(*)())code)(); | |
| ... | |
| } | |
| => | |
| define dso_local i32 @main() #0 { | |
| ... | |
| %2 = alloca [8 x i8], align 1 | |
| ... | |
| %3 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 0 | |
| store i8 -72, i8* %3, align 1 | |
| %4 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 1 | |
| store i8 1, i8* %4, align 1 | |
| %5 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 2 | |
| store i8 0, i8* %5, align 1 | |
| %6 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 3 | |
| store i8 0, i8* %6, align 1 | |
| %7 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 4 | |
| store i8 0, i8* %7, align 1 | |
| %8 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 5 | |
| store i8 -51, i8* %8, align 1 | |
| %9 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 6 | |
| store i8 -128, i8* %9, align 1 | |
| %10 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 7 | |
| store i8 0, i8* %10, align 1 | |
| ... | |
| %13 = getelementptr inbounds [8 x i8], [8 x i8]* %2, i64 0, i64 0 | |
| %14 = bitcast i8* %13 to void (...)* | |
| call void (...) %14() | |
| ... | |
| } | |
| =============================================================================== |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment