Tags: llvm reversing
Rating:
We have this file :
```
; ModuleID = 'warmup.c'
source_filename = "warmup.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@.str = private unnamed_addr constant [17 x i8] c"Enter a string: \00", align 1
@.str.1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1
@.str.2 = private unnamed_addr constant [22 x i8] c"The flag is correct!\0A\00", align 1
@.str.3 = private unnamed_addr constant [24 x i8] c"The flag is incorrect.\0A\00", align 1
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca [100 x i8], align 16
store i32 0, i32* %1, align 4
%3 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([17 x i8], [17 x i8]* @.str, i64 0, i64 0))
%4 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 0
%5 = call i32 (i8*, ...) @scanf(i8* noundef getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0), i8* noundef %4)
%6 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 0
%7 = call i64 @strlen(i8* noundef %6)
%8 = icmp ne i64 %7, 39
br i1 %8, label %9, label %10
9: ; preds = %0
call void @exit(i32 noundef 0) #3
unreachable
10: ; preds = %0
%11 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 28
%12 = load i8, i8* %11, align 4
%13 = sext i8 %12 to i32
%14 = icmp eq i32 %13, 55
br i1 %14, label %15, label %207
15: ; preds = %10
%16 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 30
%17 = load i8, i8* %16, align 2
%18 = sext i8 %17 to i32
%19 = icmp eq i32 %18, 110
br i1 %19, label %20, label %207
20: ; preds = %15
%21 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 29
%22 = load i8, i8* %21, align 1
%23 = sext i8 %22 to i32
%24 = icmp eq i32 %23, 49
br i1 %24, label %25, label %207
25: ; preds = %20
%26 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 36
%27 = load i8, i8* %26, align 4
%28 = sext i8 %27 to i32
%29 = icmp eq i32 %28, 53
br i1 %29, label %30, label %207
30: ; preds = %25
%31 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 13
%32 = load i8, i8* %31, align 1
%33 = sext i8 %32 to i32
%34 = icmp eq i32 %33, 121
br i1 %34, label %35, label %207
35: ; preds = %30
%36 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 18
%37 = load i8, i8* %36, align 2
%38 = sext i8 %37 to i32
%39 = icmp eq i32 %38, 95
br i1 %39, label %40, label %207
40: ; preds = %35
%41 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 2
%42 = load i8, i8* %41, align 2
%43 = sext i8 %42 to i32
%44 = icmp eq i32 %43, 77
br i1 %44, label %45, label %207
45: ; preds = %40
%46 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 15
%47 = load i8, i8* %46, align 1
%48 = sext i8 %47 to i32
%49 = icmp eq i32 %48, 51
br i1 %49, label %50, label %207
50: ; preds = %45
%51 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 34
%52 = load i8, i8* %51, align 2
%53 = sext i8 %52 to i32
%54 = icmp eq i32 %53, 48
br i1 %54, label %55, label %207
55: ; preds = %50
%56 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 7
%57 = load i8, i8* %56, align 1
%58 = sext i8 %57 to i32
%59 = icmp eq i32 %58, 48
br i1 %59, label %60, label %207
60: ; preds = %55
%61 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 24
%62 = load i8, i8* %61, align 8
%63 = sext i8 %62 to i32
%64 = icmp eq i32 %63, 102
br i1 %64, label %65, label %207
65: ; preds = %60
%66 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 17
%67 = load i8, i8* %66, align 1
%68 = sext i8 %67 to i32
%69 = icmp eq i32 %68, 102
br i1 %69, label %70, label %207
70: ; preds = %65
%71 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 26
%72 = load i8, i8* %71, align 2
%73 = sext i8 %72 to i32
%74 = icmp eq i32 %73, 48
br i1 %74, label %75, label %207
75: ; preds = %70
%76 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 25
%77 = load i8, i8* %76, align 1
%78 = sext i8 %77 to i32
%79 = icmp eq i32 %78, 49
br i1 %79, label %80, label %207
80: ; preds = %75
%81 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 10
%82 = load i8, i8* %81, align 2
%83 = sext i8 %82 to i32
%84 = icmp eq i32 %83, 100
br i1 %84, label %85, label %207
85: ; preds = %80
%86 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 27
%87 = load i8, i8* %86, align 1
%88 = sext i8 %87 to i32
%89 = icmp eq i32 %88, 52
br i1 %89, label %90, label %207
90: ; preds = %85
%91 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 3
%92 = load i8, i8* %91, align 1
%93 = sext i8 %92 to i32
%94 = icmp eq i32 %93, 123
br i1 %94, label %95, label %207
95: ; preds = %90
%96 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 23
%97 = load i8, i8* %96, align 1
%98 = sext i8 %97 to i32
%99 = icmp eq i32 %98, 95
br i1 %99, label %100, label %207
100: ; preds = %95
%101 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 19
%102 = load i8, i8* %101, align 1
%103 = sext i8 %102 to i32
%104 = icmp eq i32 %103, 49
br i1 %104, label %105, label %207
105: ; preds = %100
%106 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 21
%107 = load i8, i8* %106, align 1
%108 = sext i8 %107 to i32
%109 = icmp eq i32 %108, 95
br i1 %109, label %110, label %207
110: ; preds = %105
%111 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 31
%112 = load i8, i8* %111, align 1
%113 = sext i8 %112 to i32
%114 = icmp eq i32 %113, 57
br i1 %114, label %115, label %207
115: ; preds = %110
%116 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 8
%117 = load i8, i8* %116, align 8
%118 = sext i8 %117 to i32
%119 = icmp eq i32 %118, 117
br i1 %119, label %120, label %207
120: ; preds = %115
%121 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 37
%122 = load i8, i8* %121, align 1
%123 = sext i8 %122 to i32
%124 = icmp eq i32 %123, 51
br i1 %124, label %125, label %207
125: ; preds = %120
%126 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 11
%127 = load i8, i8* %126, align 1
%128 = sext i8 %127 to i32
%129 = icmp eq i32 %128, 95
br i1 %129, label %130, label %207
130: ; preds = %125
%131 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 33
%132 = load i8, i8* %131, align 1
%133 = sext i8 %132 to i32
%134 = icmp eq i32 %133, 104
br i1 %134, label %135, label %207
135: ; preds = %130
%136 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 1
%137 = load i8, i8* %136, align 1
%138 = sext i8 %137 to i32
%139 = icmp eq i32 %138, 83
br i1 %139, label %140, label %207
140: ; preds = %135
%141 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 0
%142 = load i8, i8* %141, align 16
%143 = sext i8 %142 to i32
%144 = icmp eq i32 %143, 66
br i1 %144, label %145, label %207
145: ; preds = %140
%146 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 22
%147 = load i8, i8* %146, align 2
%148 = sext i8 %147 to i32
%149 = icmp eq i32 %148, 52
br i1 %149, label %150, label %207
150: ; preds = %145
%151 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 32
%152 = load i8, i8* %151, align 16
%153 = sext i8 %152 to i32
%154 = icmp eq i32 %153, 95
br i1 %154, label %155, label %207
155: ; preds = %150
%156 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 16
%157 = load i8, i8* %156, align 16
%158 = sext i8 %157 to i32
%159 = icmp eq i32 %158, 49
br i1 %159, label %160, label %207
160: ; preds = %155
%161 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 12
%162 = load i8, i8* %161, align 4
%163 = sext i8 %162 to i32
%164 = icmp eq i32 %163, 109
br i1 %164, label %165, label %207
165: ; preds = %160
%166 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 38
%167 = load i8, i8* %166, align 2
%168 = sext i8 %167 to i32
%169 = icmp eq i32 %168, 125
br i1 %169, label %170, label %207
170: ; preds = %165
%171 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 35
%172 = load i8, i8* %171, align 1
%173 = sext i8 %172 to i32
%174 = icmp eq i32 %173, 117
br i1 %174, label %175, label %207
175: ; preds = %170
%176 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 6
%177 = load i8, i8* %176, align 2
%178 = sext i8 %177 to i32
%179 = icmp eq i32 %178, 102
br i1 %179, label %180, label %207
180: ; preds = %175
%181 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 9
%182 = load i8, i8* %181, align 1
%183 = sext i8 %182 to i32
%184 = icmp eq i32 %183, 110
br i1 %184, label %185, label %207
185: ; preds = %180
%186 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 14
%187 = load i8, i8* %186, align 2
%188 = sext i8 %187 to i32
%189 = icmp eq i32 %188, 53
br i1 %189, label %190, label %207
190: ; preds = %185
%191 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 4
%192 = load i8, i8* %191, align 4
%193 = sext i8 %192 to i32
%194 = icmp eq i32 %193, 49
br i1 %194, label %195, label %207
195: ; preds = %190
%196 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 5
%197 = load i8, i8* %196, align 1
%198 = sext i8 %197 to i32
%199 = icmp eq i32 %198, 95
br i1 %199, label %200, label %207
200: ; preds = %195
%201 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 20
%202 = load i8, i8* %201, align 4
%203 = sext i8 %202 to i32
%204 = icmp eq i32 %203, 110
br i1 %204, label %205, label %207
205: ; preds = %200
%206 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([22 x i8], [22 x i8]* @.str.2, i64 0, i64 0))
br label %209
207: ; preds = %200, %195, %190, %185, %180, %175, %170, %165, %160, %155, %150, %145, %140, %135, %130, %125, %120, %115, %110, %105, %100, %95, %90, %85, %80, %75, %70, %65, %60, %55, %50, %45, %40, %35, %30, %25, %20, %15, %10
%208 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([24 x i8], [24 x i8]* @.str.3, i64 0, i64 0))
br label %209
209: ; preds = %207, %205
ret i32 0
}
declare i32 @printf(i8* noundef, ...) #1
declare i32 @scanf(i8* noundef, ...) #1
declare i64 @strlen(i8* noundef) #1
; Function Attrs: noreturn
declare void @exit(i32 noundef) #2
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #2 = { noreturn "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #3 = { noreturn }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 1}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1"}
```
With somes research, we can find his format is llvm
We can execute the program with lli command, on ubuntu 22 after we installed llvm
We can easily find a decompiler named llvm2c (https://github.com/staticafi/llvm2c), if we excute it we have a c program with imbricated if used to verify a string
Here is the c program :
```
// function declarations
extern void exit(unsigned int var0);
int main(void);
extern unsigned int printf(unsigned char* var0, ...);
extern unsigned int scanf(unsigned char* var0, ...);
extern unsigned long strlen(unsigned char* var0);
// global variable definitions
unsigned char _str[17] = {69,110,116,101,114,32,97,32,115,116,114,105,110,103,58,32,0,};
unsigned char _str_1[3] = {37,115,0,};
unsigned char _str_2[22] = {84,104,101,32,102,108,97,103,32,105,115,32,99,111,114,114,101,99,116,33,10,0,};
unsigned char _str_3[24] = {84,104,101,32,102,108,97,103,32,105,115,32,105,110,99,111,114,114,101,99,116,46,10,0,};
int main(void){
unsigned int var0;
unsigned char var1[100];
block0:
var0 = 0;
printf(&(_str[0]));
scanf(&(_str_1[0]), &(var1[0]));
if (strlen(&(var1[0])) != 39) {
exit(0);
__asm__("int3"
:
:
:
);
} else {
if (((int)((char)(var1[28]))) == 55) {
if (((int)((char)(var1[30]))) == 110) {
if (((int)((char)(var1[29]))) == 49) {
if (((int)((char)(var1[36]))) == 53) {
if (((int)((char)(var1[13]))) == 121) {
if (((int)((char)(var1[18]))) == 95) {
if (((int)((char)(var1[2]))) == 77) {
if (((int)((char)(var1[15]))) == 51) {
if (((int)((char)(var1[34]))) == 48) {
if (((int)((char)(var1[7]))) == 48) {
if (((int)((char)(var1[24]))) == 102) {
if (((int)((char)(var1[17]))) == 102) {
if (((int)((char)(var1[26]))) == 48) {
if (((int)((char)(var1[25]))) == 49) {
if (((int)((char)(var1[10]))) == 100) {
if (((int)((char)(var1[27]))) == 52) {
if (((int)((char)(var1[3]))) == 123) {
if (((int)((char)(var1[23]))) == 95) {
if (((int)((char)(var1[19]))) == 49) {
if (((int)((char)(var1[21]))) == 95) {
if (((int)((char)(var1[31]))) == 57) {
if (((int)((char)(var1[8]))) == 117) {
if (((int)((char)(var1[37]))) == 51) {
if (((int)((char)(var1[11]))) == 95) {
if (((int)((char)(var1[33]))) == 104) {
if (((int)((char)(var1[1]))) == 83) {
if (((int)((char)(var1[0]))) == 66) {
if (((int)((char)(var1[22]))) == 52) {
if (((int)((char)(var1[32]))) == 95) {
if (((int)((char)(var1[16]))) == 49) {
if (((int)((char)(var1[12]))) == 109) {
if (((int)((char)(var1[38]))) == 125) {
if (((int)((char)(var1[35]))) == 117) {
if (((int)((char)(var1[6]))) == 102) {
if (((int)((char)(var1[9]))) == 110) {
if (((int)((char)(var1[14]))) == 53) {
if (((int)((char)(var1[4]))) == 49) {
if (((int)((char)(var1[5]))) == 95) {
if (((int)((char)(var1[20]))) == 110) {
printf(&(_str_2[0]));
return 0;
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
} else {
goto block42;
}
}
block42:
printf(&(_str_3[0]));
return 0;
}
```
We can extract the if and save it, then we can parse it to onlly keep the index of the table and the ascii value it verify under this format: column,value
28,55
30,110
29,49
36,53
13,121
18,95
2,77
15,51
34,48
7,48
24,102
17,102
26,48
25,49
10,100
27,52
3,123
23,95
19,49
21,95
31,57
8,117
37,51
11,95
33,104
1,83
0,66
22,52
32,95
16,49
12,109
38,125
35,117
6,102
9,110
14,53
4,49
5,95
20,110
Then we just have to quickly order it by in python (i don't have the program there), and we get the flag.
BSM{1_f0und_my531f_1n_4_f10471n9_h0u53}