1 00:00:00,410 --> 00:00:01,640 Hello, everyone. 2 00:00:01,640 --> 00:00:05,720 Welcome to the concluding lecture of our Hello World Shellcode Series. 3 00:00:05,870 --> 00:00:11,420 Throughout this series, we have embarked on a journey to explore the world of shell coding. 4 00:00:11,450 --> 00:00:17,000 Taking our first steps toward understanding the intricacies of low level programming. 5 00:00:17,030 --> 00:00:21,560 Today, we are going to delve into the art of debugging and fixing. 6 00:00:21,560 --> 00:00:27,840 One of the most common uses that Shell coders encounter the segmentation fault. 7 00:00:27,860 --> 00:00:29,110 I hate this word. 8 00:00:29,120 --> 00:00:35,870 So in our previous sessions we have learned how to craft shell code to print Hello world to the console 9 00:00:35,870 --> 00:00:38,920 using various techniques and assembler language concepts. 10 00:00:38,930 --> 00:00:45,950 However, as we delve into the realm of shell coding, we have discovered that things don't go always 11 00:00:45,950 --> 00:00:52,760 as smoothly as planned, and it's not uncommon to encounter errors, especially when working with delicate 12 00:00:52,760 --> 00:00:56,740 balance between the low level memory management and system calls. 13 00:00:56,750 --> 00:01:02,850 And today we will equip ourselves with the skills needed to identify and rectify one of the most vexing 14 00:01:02,850 --> 00:01:06,170 errors in shell coding the segmentation fault. 15 00:01:06,180 --> 00:01:09,720 So now let's actually compile our program again. 16 00:01:09,900 --> 00:01:12,770 And as you can see, we have Main.c and hello dot ASM. 17 00:01:12,780 --> 00:01:16,770 So we actually are we have actually already got this here. 18 00:01:16,770 --> 00:01:22,740 But firstly, I have copied this Objdump command here because it's actually takes pretty time from our 19 00:01:22,740 --> 00:01:24,300 lectures to write it down. 20 00:01:24,300 --> 00:01:30,360 And I have also shared this comment with you in our attachment sections here. 21 00:01:30,360 --> 00:01:40,260 Now what we're going to do here is we will firstly compile this, assemble this here Elf 64 and Hello 22 00:01:40,290 --> 00:01:43,950 dot ASM and we will create an object file here. 23 00:01:43,950 --> 00:01:47,610 Hello Dot no object here. 24 00:01:47,610 --> 00:01:53,700 And we had the warning here label alone in line with other column might be an error here. 25 00:01:53,700 --> 00:01:54,590 Let's see what it. 26 00:01:54,660 --> 00:01:58,800 Yeah we need to adjust the colon here and compile it again. 27 00:02:00,100 --> 00:02:01,840 This is this is not an error here. 28 00:02:01,840 --> 00:02:03,860 This was just a warning and that's it. 29 00:02:03,880 --> 00:02:09,370 We our code is compiled, assembled without errors here. 30 00:02:09,370 --> 00:02:12,370 And as you can see, we have the file here, object file here. 31 00:02:12,370 --> 00:02:16,780 And now what we're going to do is we will use the LD here linking for linking here. 32 00:02:16,820 --> 00:02:17,740 Hello. 33 00:02:18,520 --> 00:02:18,940 Hello. 34 00:02:18,940 --> 00:02:22,420 Dot org here and output file is going to be. 35 00:02:22,450 --> 00:02:23,350 Hello. 36 00:02:24,300 --> 00:02:24,800 World. 37 00:02:24,950 --> 00:02:27,860 And as you can see, we have this executable file now. 38 00:02:27,860 --> 00:02:33,860 So when we run this and as you can see, we are printing the Hello world now. 39 00:02:34,780 --> 00:02:41,890 And we will use that command here, this long command here, which we will produce this shellcode from 40 00:02:41,890 --> 00:02:45,190 the output here of our executable program. 41 00:02:45,430 --> 00:02:56,050 Now let's actually press enter and no such file because we changed our executable file here to Hello 42 00:02:56,050 --> 00:02:59,500 world and this is our shellcode. 43 00:03:00,370 --> 00:03:03,490 And you might see that this bad characters here. 44 00:03:03,490 --> 00:03:07,780 But don't worry, these are not actually bad characters now. 45 00:03:08,230 --> 00:03:09,790 And you will see why. 46 00:03:09,820 --> 00:03:12,400 Now, now what we're going to do is we will again. 47 00:03:12,460 --> 00:03:17,650 Let's actually objdump d m Intel. 48 00:03:18,050 --> 00:03:19,390 Hello world. 49 00:03:19,390 --> 00:03:19,990 Right? 50 00:03:19,990 --> 00:03:23,830 And as you can see here, we have not bad characters here at all. 51 00:03:24,640 --> 00:03:31,030 But even though we have that bad characters in our shellcode but they are not actually bad characters 52 00:03:31,030 --> 00:03:34,490 and you will learn that why in next lectures. 53 00:03:34,730 --> 00:03:38,330 Now here, as you can see, there are. 54 00:03:38,360 --> 00:03:43,820 Okay, so this was the same code in previous lecture, so we don't have any errors here, right? 55 00:03:43,820 --> 00:03:45,200 So that's okay. 56 00:03:45,200 --> 00:03:52,010 But what we had here is the error with the main key here, which we got the segmentation fault from 57 00:03:52,010 --> 00:03:52,250 it. 58 00:03:52,250 --> 00:03:56,060 So since we have compiled it, let's actually sorry for this here. 59 00:03:56,060 --> 00:03:59,840 So let's now copy this here. 60 00:04:01,070 --> 00:04:03,980 And paste to our here. 61 00:04:05,570 --> 00:04:06,230 That's it. 62 00:04:06,260 --> 00:04:10,370 This was the same shell code here from our previous lecture. 63 00:04:10,400 --> 00:04:18,920 Now, what we're going to do is we will compile this C program here and see what happens. 64 00:04:18,950 --> 00:04:20,510 C program and see what happens here. 65 00:04:20,810 --> 00:04:23,030 And what we're going to do here is. 66 00:04:23,950 --> 00:04:32,740 We will firstly run our GCC and there's a new flag here we will use. 67 00:04:32,740 --> 00:04:38,650 So this flag is used to specify the optimization level for the compilation process and in this case, 68 00:04:38,650 --> 00:04:43,450 the all zero uppercase all zero option indicates no optimization. 69 00:04:43,450 --> 00:04:49,180 So optimization is the process of transforming the code to improve its performance or reduce its size. 70 00:04:49,180 --> 00:04:55,270 So by using this, you are requesting no optimizations to be applied which can be useful for debugging 71 00:04:55,270 --> 00:05:02,830 purposes as it keeps the code closer to its original form, making making it easier to analyze and we 72 00:05:02,830 --> 00:05:06,520 will use F no stack protector. 73 00:05:06,820 --> 00:05:11,290 So this flag instructs the compiler to disable the stack protector feature. 74 00:05:11,290 --> 00:05:13,960 So stack protection protection. 75 00:05:13,960 --> 00:05:21,880 Also stack protection, also known as Stack Smashing Protection or Stack Canaries is a security mechanism 76 00:05:21,880 --> 00:05:28,670 designed to detect and prevent buffer overflow attacks by monitoring changes to the stack. 77 00:05:28,700 --> 00:05:35,990 Disabling stack protection might be done initially and intentionally for certain reasons, but it can 78 00:05:35,990 --> 00:05:40,160 be potentially make the code more vulnerable to attacks. 79 00:05:40,160 --> 00:05:43,970 And here we will also use the Z exec stack. 80 00:05:44,000 --> 00:05:48,230 This flag modifies the executables stack permissions to allow execution. 81 00:05:48,230 --> 00:05:54,590 And in some systems, the stack memory is marked as non-executable by default to prevent certain types 82 00:05:54,590 --> 00:05:55,460 of attacks. 83 00:05:55,460 --> 00:06:03,350 And using the Z exec stack really relaxes this restriction and allows the stack to be executed and which 84 00:06:03,350 --> 00:06:10,400 can be useful in some specific scenarios but might also be introduced security risk if not handled carefully. 85 00:06:10,400 --> 00:06:18,110 And this is why what we want from this code here and what we have here and main last see, this is the 86 00:06:18,110 --> 00:06:27,110 name of the source file that we will want to compile and it should be a valid C source with the file, 87 00:06:27,110 --> 00:06:28,190 the C extension here. 88 00:06:28,190 --> 00:06:31,430 And as you can see, our program is compiled here. 89 00:06:31,430 --> 00:06:39,050 So in summary, the provided compilation command is used to compile the C source code here with Shellcode. 90 00:06:40,170 --> 00:06:48,130 And the command specifies no optimization, disables stack protection and modify stack permissions to 91 00:06:48,130 --> 00:06:50,100 a low execution here. 92 00:06:50,100 --> 00:06:51,300 So that's it. 93 00:06:51,300 --> 00:06:57,330 And now what we're going to do is we will run this here, which is it should be a dot out. 94 00:06:57,360 --> 00:06:58,530 Yeah, a dot out. 95 00:06:58,530 --> 00:07:01,320 And as you can see, we got the segmentation fault. 96 00:07:01,350 --> 00:07:03,270 Same fault here. 97 00:07:03,270 --> 00:07:06,210 And there's an easy fix for that. 98 00:07:06,210 --> 00:07:07,680 But before that. 99 00:07:08,490 --> 00:07:18,660 I want to introduce you to some useful tool for debugging here, which is. 100 00:07:23,090 --> 00:07:24,260 Valgrind. 101 00:07:25,070 --> 00:07:32,570 And as you've seen, debugging can be quite challenging, especially when dealing with issues like segmentation, 102 00:07:32,570 --> 00:07:33,870 fault and memory errors. 103 00:07:33,890 --> 00:07:40,250 And fortunately we have the valgrind here is to streamline the process and provide us with detailed 104 00:07:40,250 --> 00:07:42,170 insights into program's behavior. 105 00:07:42,170 --> 00:07:46,220 So it's actually it has very, very easy installation process. 106 00:07:46,220 --> 00:07:50,540 Just write sudo apt get install valgrind and that's it. 107 00:07:50,540 --> 00:07:52,970 Here, enter password and that's it. 108 00:07:53,210 --> 00:07:55,850 The valgrind is installed as easy as that. 109 00:07:55,850 --> 00:08:03,170 And what we're going to do here is now and before we delve into the realm of valgrind, let's ensure 110 00:08:03,170 --> 00:08:07,130 we have um, installed in our system. 111 00:08:07,130 --> 00:08:11,390 In order to do that, we will use valgrind v that's it. 112 00:08:11,390 --> 00:08:17,990 And as you can see here, we have valgrind installed here and what we're going to do is we will just 113 00:08:17,990 --> 00:08:19,340 use valgrind. 114 00:08:20,770 --> 00:08:24,760 Leak check equals full. 115 00:08:24,760 --> 00:08:27,700 And now we will enter our output. 116 00:08:27,730 --> 00:08:28,540 That's it. 117 00:08:29,600 --> 00:08:31,760 And as you can see here, valgrind. 118 00:08:33,050 --> 00:08:36,530 Actually gave us pretty useful features here. 119 00:08:36,530 --> 00:08:37,400 Information. 120 00:08:37,400 --> 00:08:42,050 So you might be wondering why we should opt valgrind instead of other debugging methods. 121 00:08:42,050 --> 00:08:42,440 So. 122 00:08:42,440 --> 00:08:44,930 Well, here's the deal here. 123 00:08:44,930 --> 00:08:46,250 So valgrind. 124 00:08:46,430 --> 00:08:53,120 Valgrind is a remarkably faster and more user friendly when it comes to spotting memory errors, particularly 125 00:08:53,120 --> 00:08:59,090 when we are working with non-optimized builds that include debugging symbols valgrind becomes a powerful 126 00:08:59,090 --> 00:09:09,350 ally and it not only pinpoints where segmentation fault occurred but also sheds light on why it happened. 127 00:09:09,350 --> 00:09:16,280 And this level of insight is invaluable in diagnosing and fixing user uses promptly and in addition 128 00:09:16,280 --> 00:09:22,820 to tracking down memory uses, Valgrind helps us to understand how our program interacts with memory 129 00:09:22,820 --> 00:09:26,750 and system calls, providing us with deeper understanding of its behavior. 130 00:09:26,750 --> 00:09:32,760 And this knowledge not only makes the debugging smoother, but also makes us better programmers by exposing 131 00:09:32,760 --> 00:09:36,860 us to the nitty gritty of memory management and execution flow. 132 00:09:36,870 --> 00:09:43,620 So now what we're going to do is we are seeing the errors here, the note errors, the information here, 133 00:09:43,830 --> 00:09:56,970 and at first we have the valgrind version copyright and the fact that it's using the lib vex and essentially 134 00:09:56,970 --> 00:10:03,450 it's this is just an introduction here and we have this line of command shows that was run in this case 135 00:10:03,450 --> 00:10:07,080 A.out, which is our Shellcode program. 136 00:10:07,080 --> 00:10:12,990 And also what we have here is the my Shellcode length. 137 00:10:12,990 --> 00:10:16,440 This is the output or the print section. 138 00:10:16,440 --> 00:10:26,490 So this this part appears to be custom output that we did here and it indicates the length of our shellcode 139 00:10:26,490 --> 00:10:27,660 as we wrote it. 140 00:10:27,660 --> 00:10:28,950 It should do that. 141 00:10:28,950 --> 00:10:32,580 So the from there it's all okay here. 142 00:10:32,610 --> 00:10:38,610 Our program executes right and what we have need to do it. 143 00:10:38,610 --> 00:10:44,310 And as you can see here, this this is the 55th of one bytes, right? 144 00:10:44,310 --> 00:10:48,390 So the length is actually meaning bytes in our code, right? 145 00:10:48,390 --> 00:10:49,230 So. 146 00:10:51,430 --> 00:10:55,810 The critical part here is this. 147 00:10:56,980 --> 00:10:59,860 Which indicates the segmentation fault error. 148 00:10:59,890 --> 00:11:00,610 Right. 149 00:11:00,610 --> 00:11:06,460 So we have the processor with default action of signal 11. 150 00:11:06,460 --> 00:11:07,210 So. 151 00:11:08,540 --> 00:11:14,060 This tells us that the program terminated due to a segmentation fault. 152 00:11:14,180 --> 00:11:16,790 Sigsegv Right. 153 00:11:16,790 --> 00:11:18,780 Which is a memory access violation. 154 00:11:18,800 --> 00:11:19,430 Right. 155 00:11:19,430 --> 00:11:25,400 So and we also have bad permissions for mapped region at address zero. 156 00:11:26,180 --> 00:11:29,150 So at address ten 040. 157 00:11:31,310 --> 00:11:38,090 That this suggests that there was an attempt to access memory at this address, but the permissions 158 00:11:38,090 --> 00:11:41,630 for that memory region were not valid. 159 00:11:42,080 --> 00:11:45,530 And we also have this question marks here. 160 00:11:45,530 --> 00:11:54,260 And this in-home typhoon, source Shellcode out indicates that the problem occurred at this address 161 00:11:54,260 --> 00:12:02,870 but is unable to provide specific information about what code or operation led to the user here. 162 00:12:02,870 --> 00:12:10,290 And we also this below main information here we have this and 58. 163 00:12:10,310 --> 00:12:13,640 So this shows the call stack at the time of the error. 164 00:12:13,640 --> 00:12:19,910 So it appears that the user occurred below main function in some system library code. 165 00:12:19,910 --> 00:12:22,400 And we also have the heap summary here. 166 00:12:22,400 --> 00:12:30,490 This section provides information about heap memory usage and is in use at exit here. 167 00:12:30,590 --> 00:12:33,300 The 1024 bytes in one blocks. 168 00:12:33,300 --> 00:12:33,930 Let me actually check. 169 00:12:34,080 --> 00:12:35,910 Is my voice recording here? 170 00:12:35,910 --> 00:12:36,240 Yeah. 171 00:12:36,270 --> 00:12:37,020 Perfect. 172 00:12:37,020 --> 00:12:48,060 So 1024 bytes in one blocks tells us that there were 1024 bytes of heap memory in use at the time the 173 00:12:48,060 --> 00:12:49,470 program exited. 174 00:12:49,800 --> 00:13:00,150 And we also have total heap usage, which is 103 and 1024 bytes allocated indicates that the during 175 00:13:00,150 --> 00:13:08,610 the program's execution we had these logs frees and bytes allocated and obviously we have the leak summary 176 00:13:08,610 --> 00:13:15,120 here which we did not have any leaks definitely lost and in the indirect loss, possibly lost. 177 00:13:15,120 --> 00:13:22,320 So this definitely loss obviously refers to memory that was allocated but not freed during the program's 178 00:13:22,320 --> 00:13:23,100 execution. 179 00:13:23,100 --> 00:13:29,940 In this case, there were zero bytes lost and in zero blocks and indirect lost. 180 00:13:29,940 --> 00:13:39,290 So and indirect lost and possible errors are similar but refer to more complex scenarios of lost memory. 181 00:13:39,290 --> 00:13:43,400 And in this case, there were zero bytes indirectly or possibly lost. 182 00:13:43,400 --> 00:13:48,500 And we also have the still reachable 1024 bytes in one block. 183 00:13:48,500 --> 00:13:56,660 So this indicates that indicates that was allocated but still reachable at the end of the program. 184 00:13:56,660 --> 00:14:03,500 So in this case, 1024 bytes were still reachable, which may not necessarily be a problem depending 185 00:14:03,500 --> 00:14:07,190 on the program's design and suppressed. 186 00:14:07,190 --> 00:14:12,170 Here we have the refers to the errors valgrind has suppressed or ignored. 187 00:14:12,170 --> 00:14:15,530 In this case there were no suppressed errors. 188 00:14:15,530 --> 00:14:22,790 And also we have the reachable blocks which is and to see them return the leak check full show leak 189 00:14:23,120 --> 00:14:32,810 kinds all and obviously in order to do that you will need to use rerun with this command with both of 190 00:14:32,810 --> 00:14:33,230 them. 191 00:14:33,230 --> 00:14:38,720 But in this case, this actually doesn't we don't need that information in this program here. 192 00:14:38,990 --> 00:14:43,070 And error summary zero errors from zero contexts here. 193 00:14:43,850 --> 00:14:48,290 And finally, this section provides a summary of detected errors. 194 00:14:48,290 --> 00:14:55,070 In this case, it reports that there were zero errors from zero contexts and no errors were suppressed. 195 00:14:55,070 --> 00:15:02,480 So the program then executed with a segmentation fault message, as you can see here. 196 00:15:03,700 --> 00:15:07,540 Now, the problem is that, as you can see here. 197 00:15:08,810 --> 00:15:14,930 The problem seems like we are not reaching the chord array here. 198 00:15:18,110 --> 00:15:24,440 Now I will give you 10s to find out why we are not reaching to this array. 199 00:15:41,820 --> 00:15:44,760 So I will start explaining that now. 200 00:15:44,760 --> 00:15:51,480 So the segmentation fault, usually in the original code arises from the fact that the shell code, 201 00:15:51,510 --> 00:15:56,730 which is code is defined at the global scope. 202 00:15:56,760 --> 00:16:04,110 This means that it's stored in a section of memory that may have certain protections or permissions 203 00:16:04,110 --> 00:16:09,900 which can cause problems when attempting to execute shell code from such a region. 204 00:16:10,980 --> 00:16:16,620 So in this code here, we need to fix that. 205 00:16:16,650 --> 00:16:21,980 So we will move that inside the main function. 206 00:16:22,380 --> 00:16:25,470 But before the printf, that's it. 207 00:16:26,920 --> 00:16:29,650 And in this fixed code. 208 00:16:30,250 --> 00:16:34,570 The shellcode is moved inside the main function resulting in it. 209 00:16:35,350 --> 00:16:38,200 Being stored in the stack frame of the main function. 210 00:16:38,200 --> 00:16:45,790 So the stack is typically executable, making it suitable location to store and execute shellcode. 211 00:16:45,820 --> 00:16:51,780 By doing so, the shellcode will have appropriate permissions and executed. 212 00:16:51,780 --> 00:16:54,730 It will not trigger a segmentation fault. 213 00:16:55,300 --> 00:17:03,130 And now what we're going to do is let's actually save this and let's go to our GCC and compile this 214 00:17:03,220 --> 00:17:03,850 actually. 215 00:17:05,740 --> 00:17:06,670 Use that here. 216 00:17:06,670 --> 00:17:09,490 So GCC Oa0 f No. 217 00:17:09,490 --> 00:17:10,160 Stack protector. 218 00:17:10,180 --> 00:17:11,800 The exec stack. 219 00:17:11,830 --> 00:17:13,150 And that's it. 220 00:17:13,450 --> 00:17:17,470 Now we have that out here and that's it. 221 00:17:17,500 --> 00:17:21,400 We have the successfully executed shellcode. 222 00:17:21,430 --> 00:17:22,120 Perfect. 223 00:17:23,340 --> 00:17:26,520 Now what we're going to do is this is the last lecture. 224 00:17:26,520 --> 00:17:32,790 And to summarize, the original segmentation fault usually occurred because the shellcode was stored 225 00:17:32,790 --> 00:17:41,100 in a region of memory that might not have had the necessary permissions for execution, and the fix 226 00:17:41,100 --> 00:17:46,650 involved moving the shellcode into the local scope of the main function, ensuring that it stored in 227 00:17:46,650 --> 00:17:49,960 a memory region where the execution is allowed. 228 00:17:49,980 --> 00:17:56,880 So the simple change prevents a segmentation fault and allows the shellcode to be executed successfully.