[00:00.000 --> 00:04.360] So, this is the outline. [00:04.720 --> 00:08.060] Number one, we will introduce our malware scouting system. [00:08.220 --> 00:12.280] And number two, we will show you how we designed the Dalvik bytecode loader. [00:12.300 --> 00:17.180] And number three, we will go through two cases of real malware analysis using Quark Engine. [00:17.380 --> 00:21.760] And number four, we will share our strategy of generating the detection rules. [00:22.080 --> 00:24.800] And the last thing, yes, the feature works. [00:24.800 --> 00:27.140] Because we still have a lot of things to do. [00:27.980 --> 00:31.800] Alright, so let's introduce the malware scoring system. [00:31.980 --> 00:38.500] As we know, when developing a malware analysis engine, it is important to have a scoring system. [00:38.500 --> 00:43.580] However, those systems are either business secrets or just too complicated. [00:43.680 --> 00:50.080] Therefore, we decided to create a simple but solid one and take that as a challenge. [00:50.400 --> 00:54.300] And since we wanted to design a novel scoring system, [00:54.300 --> 00:59.570] we stopped reading and decoding whatever people do in the field of cybersecurity. [01:00.000 --> 01:04.570] Because we don't want our ideas to be subjected to the existing systems. [01:05.180 --> 01:10.240] So we started to find ideas in fields other than cybersecurity. [01:10.240 --> 01:12.500] And luckily, we found one. [01:13.000 --> 01:17.200] Yes, the best practice we found is the criminal law. [01:17.720 --> 01:23.740] So, when sentenced a penalty for a criminal, the judge weighs the penalties based on the criminal law. [01:23.740 --> 01:27.320] And after decoding the law, we find principles behind it. [01:27.320 --> 01:31.040] And we develop a scoring system for Android malware. [01:31.960 --> 01:35.420] There are only eight principles decoded from the criminal law. [01:35.420 --> 01:38.020] And I'll go through it in the following slides. [01:38.120 --> 01:40.360] Now let's see principle number one. [01:40.360 --> 01:44.700] A malware crime consists of action and targets. [01:44.920 --> 01:50.220] In the criminal law, the definition of a crime consists of action and targets. [01:50.220 --> 01:53.680] For example, steal money and kill people. [01:53.680 --> 02:00.360] So, with this principle in mind, we develop the definition of a crime for Android malware. [02:00.500 --> 02:05.920] And the definition is, the malware crime consists of action and targets. [02:06.260 --> 02:11.540] For example, steal photos or steal your banking account password. [02:12.620 --> 02:15.000] Now let's see principle number two. [02:15.000 --> 02:19.400] We consider that the loss of fame is greater than the loss of wealth. [02:19.400 --> 02:25.640] So, in the criminal law, physical body injury is more serious than psychological injury. [02:25.700 --> 02:32.560] So, the principle we decoded here is, when things are hard to recover, we consider it a felony. [02:32.900 --> 02:37.240] So, with this principle decoded, we develop our second principle. [02:37.240 --> 02:45.120] We consider the loss of fame is greater than the loss of wealth, because it's easier to make money back than rebuild your reputation. [02:45.820 --> 02:49.760] Okay, now let's see principle number three, arithmetic sequence. [02:50.080 --> 02:59.620] In the criminal law, when a murderer is sentenced to 20 years in prison, and a robber is sentenced to 7 years in prison for his crime, why the number? [02:59.640 --> 03:03.180] Why 20 and 7 years? Why the number? [03:03.180 --> 03:10.180] We found no obvious principles in the criminal law, so we use arithmetic sequence to weigh the penalty of each crime. [03:10.180 --> 03:17.740] For example, the penalty weight of Y1 is 10, and Y2 is 20, and Y3 is 30, etc. [03:18.800 --> 03:22.520] So, now let's see the most important part of the scoring system. [03:22.600 --> 03:26.720] We create an order theory, which consists of three principles. [03:26.720 --> 03:29.900] Here are principle number four, five, and number six. [03:30.280 --> 03:32.380] Now, let's look at principle number four. [03:32.380 --> 03:36.360] The later the stage, the more we're sure that a crime is practiced. [03:36.360 --> 03:42.920] As mentioned in chapter four of Taiwan criminal law, each crime consists of a sequence of behaviors. [03:42.920 --> 03:46.660] Those behaviors can be categorized in a specific order. [03:47.080 --> 03:49.460] So, let's take murder for example. [03:49.460 --> 03:54.520] Determined in stage one. Determined means somebody decided to kill someone. [03:54.520 --> 04:00.320] And in stage two, conspiracy. It means he or she started to make a plan for the murder. [04:00.320 --> 04:07.900] And in stage three, preparation. It means buying stuff, for example, weapons or arranging services for the murder plan. [04:08.040 --> 04:16.540] And in stage four, starts. It means when things are all set, the murderer takes action and is on the way to kill someone. [04:16.760 --> 04:22.100] And in stage five, practice. It means the murderer does pull the trigger and shoot someone. [04:22.880 --> 04:28.000] So, as we can see here, the later the stage, the more we're sure that a crime is practiced. [04:29.440 --> 04:35.320] So, with this principle in mind, we developed Android malware crime author theory. [04:35.560 --> 04:39.760] And in this theory, we also have five stages for the crime. [04:39.760 --> 04:45.120] For example, if a malware tries to send out your location data by using SMS, [04:45.560 --> 04:50.720] in stage one, we will check if related permission is requested by the malware. [04:50.720 --> 04:54.760] And then, we will check if the key native API is called. [04:54.760 --> 05:00.040] And in stage three, we will see if a certain combination of native API exists. [05:00.360 --> 05:04.180] And then, we will check if the APIs are called in a specific order. [05:04.420 --> 05:09.700] Finally, we will check if the APIs are handling the same register. [05:10.780 --> 05:16.260] Okay, so now you can see from this picture, this is a two-dimensional map for Android malware crime. [05:16.260 --> 05:19.280] For the crimes, we put them in y-axis. [05:19.280 --> 05:25.200] And for each crime, we use x-axis to see the evidence we caught for the crime. [05:25.240 --> 05:36.140] So, x5, y1 means in crime number one, we have found native APIs that are caught in a correct sequence and are handling the same register. [05:36.300 --> 05:44.880] And x3, y5 means in crime number five, we have found certain combinations of native APIs that is used in this APK. [05:44.880 --> 05:49.540] So, now let's look at principle number five. [05:49.540 --> 05:53.480] The more evidence we caught, the more penalty weight we give. [05:53.480 --> 05:59.620] So, we give stage two more weight than stage one, and stage three more weight than stage two, etc. [06:00.780 --> 06:04.840] Okay, principle number six, proportional sequence. [06:05.020 --> 06:11.500] As we decode it from the criminal law, the later the stage, the more we are sure that a crime is practiced. [06:11.500 --> 06:19.760] So, we consider proportional sequence, for example, 2 to the power of n, to present such principle in our scoring system. [06:19.900 --> 06:24.040] Alright, principle number seven, crimes are independence events. [06:24.040 --> 06:30.660] For simplicity, we assume crimes are independence events, and penalty weights can be added up directly. [06:30.800 --> 06:34.020] So, this is an example of adding up two crimes. [06:34.020 --> 06:39.860] In the malware, we find two crimes, they are stealing photos and stealing your banking account password. [06:39.860 --> 06:43.620] So, the calculation of the total penalty weights is quite simple. [06:43.620 --> 06:53.540] For example, for each crime, we use penalty weights of crime to multiply proportion of caught evidence and add up the results of the two. [06:54.040 --> 06:58.860] The last principle, principle number eight, thresholds generate system. [06:58.860 --> 07:08.520] So, after calculating the total penalty weights for a malware, we need to have threat level threshold, so that we can tell which threat level does the malware fill in. [07:08.520 --> 07:18.820] Unfortunately, we can't find them in criminal law, but we know we need to design a threshold-generated system for that, not just give any number by intuition. [07:19.180 --> 07:30.400] So, we decided that threshold for each level is the sum of the same proportion of caught evidence multiplies penalty weights of crimes. [07:30.400 --> 07:37.100] We know it's not a perfect one, but we're sure that we build a foundation for future optimization. [07:37.100 --> 07:42.580] Alright, now let's talk about the design logic of Delphi Bytecode Loader. [07:43.260 --> 07:47.000] And Junwei, he will take care of this part. [07:48.020 --> 07:53.440] Hello everyone, my name is Junwei, and I will take care of this part. [07:53.560 --> 07:59.300] So now, let's talk about the design logic of Delphi Bytecode Loader. [08:00.300 --> 08:08.680] Our Delphi Bytecode Loader is actually the implementation of the Android malware crime order theory. [08:08.680 --> 08:12.280] We implement every stage of the theory. [08:12.280 --> 08:16.600] There are five stages. The first three stages are easy. [08:16.600 --> 08:25.300] We simply use APIs in another open source tool, Android Guard, to implement the first three stages. [08:25.300 --> 08:31.300] As I just mentioned, the implementation of the first three stages are easy. [08:31.300 --> 08:35.300] But in stage 4, we need to do a little bit more. [08:35.440 --> 08:40.600] So before the implementation, we need to know what does stage 4 do. [08:41.000 --> 08:50.300] In stage 4, we find the calling sequence of native APIs and check if they are called in a specific order. [08:50.300 --> 09:04.500] For example, if a malware sends out your location data by SNS, then first it will call native API getCellLocation to get your location data, [09:04.500 --> 09:12.740] and then call native API sendTextMessage to send your location data by SNS. [09:12.740 --> 09:17.940] Normally, native APIs are wrapped in functions. [09:17.940 --> 09:24.460] So we trace back to see which function is cross-referenced from the native APIs. [09:24.460 --> 09:28.960] And we call those functions a parent function. [09:29.020 --> 09:35.930] And we will keep tracing back until we find a mutual parent function for both the native APIs. [09:36.320 --> 09:38.660] Here is the example. [09:38.660 --> 09:47.600] sendTextMessage is called by sendSNS, which is the parent function of sendTextMessage. [09:47.600 --> 09:56.400] And getCellLocation is called by getLocation, which is the parent function of getCellLocation. [09:56.400 --> 10:08.120] And if we keep tracing back, we will see that both sendSNS and getLocation shares the same parent function, sendTextMessage. [10:08.800 --> 10:21.820] And after we find the mutual parent function, we will scan through a small light code of the mutual parent function and check which function is called first. [10:21.820 --> 10:26.180] So this is the small light code of sendMessage. [10:26.400 --> 10:33.720] We can see that getLocation is called first to get location data of the cell phone. [10:33.840 --> 10:38.980] And sendSNS is called to send out the location data. [10:40.220 --> 10:49.900] And in stage 4, we found that our design can also overcome the obfuscation techniques used by the malware. [10:49.900 --> 10:56.940] When applying obfuscation techniques, functions except native APIs are renamed. [10:57.080 --> 11:02.220] This has made the decompiled source code hard to read for humans. [11:02.620 --> 11:08.140] A machine can still run the code because the logic of the code remains the same. [11:08.520 --> 11:10.840] Here is the example. [11:10.840 --> 11:19.500] When applying obfuscation techniques, native API sendTextMessage is called by function k. [11:19.500 --> 11:23.720] And function k is called by function f. [11:23.720 --> 11:29.500] The alternative API getCellLocation is called by function e. [11:29.500 --> 11:36.320] And both function e and f share the same parent function, which is a. [11:36.320 --> 11:45.660] You see, if you start reading the decompiled source code of a, it will be hard to figure out what is going on there. [11:45.660 --> 11:56.940] And by the way, since our goal is to find the mutual parent function, so it doesn't matter how many layers the wipers are. [11:57.900 --> 12:02.320] Now, let's see the implementation of stage 5. [12:02.320 --> 12:05.520] Yes, this is the most important part. [12:05.520 --> 12:12.840] In stage 5, we need to confirm that if the native APIs are handling the send register. [12:12.840 --> 12:15.880] Let's use the send example. [12:15.880 --> 12:20.480] Send out your location data by using SNS. [12:20.500 --> 12:29.360] So when native API getCellLocation is called, it will return the location data of the cell phone. [12:29.360 --> 12:42.420] And what we do in stage 5 is to check if the alternative API sendTextMessaging sends out the location data returned from getCellLocation. [12:43.040 --> 12:48.440] So in stage 5, we simulate the CPU operation. [12:48.440 --> 12:57.860] We read line by line of the Somali-like source code and operate like CPUs to get two things. [12:57.860 --> 13:02.080] First, the value of every register. [13:02.080 --> 13:08.500] Second, the information like functions who have operated the send register. [13:08.680 --> 13:13.820] To make this happen, we create a self-defined data type. [13:13.820 --> 13:16.800] We call it register object. [13:16.880 --> 13:22.080] In each register object, we store three kinds of information. [13:22.080 --> 13:24.680] No.1, the register name. [13:24.680 --> 13:27.740] No.2, the value of register. [13:27.740 --> 13:31.840] And No.3, the function who use this register. [13:31.840 --> 13:34.420] Let's see an example. [13:34.600 --> 13:37.740] So the register name is fee7. [13:37.740 --> 13:41.580] And the value of the register is a string. [13:41.580 --> 13:48.780] And the string appends the value of string1 and the result of function1. [13:48.780 --> 13:56.660] And then we can see that the register is used as the input resource of the function2. [13:56.780 --> 14:04.540] By the way, when filling the value of useByWhich function in the register object, [14:04.540 --> 14:11.620] we extend every register by cross-referencing other register objects in the table. [14:11.620 --> 14:21.040] So, for example, by cross-referencing, we know that fee8 is a string called userLocation. [14:21.040 --> 14:25.080] And fee3 is a function called getLocation. [14:25.260 --> 14:36.200] As you can see in the lower right corner, the result of getLocation is appended to the string which is userLocation. [14:36.200 --> 14:42.660] And the new string is sent out by using function sendSns. [14:42.660 --> 14:55.620] In other words, the value of register fee7 is generated by using function getLocation, which has native API 1 in it. [14:55.620 --> 15:05.420] And the value is used as an input for function sendSns, which has native API 2 in it. [15:05.420 --> 15:15.820] So now, we prove that by using the register object, we can check if the APIs are handling the same register. [15:15.820 --> 15:22.880] So after we scan through the source code, we produce dots of register objects. [15:23.180 --> 15:30.620] And those register objects will be organized when a two-dimensional Python list. [15:30.740 --> 15:34.320] It is a similar idea like hash table. [15:34.320 --> 15:39.600] We use it to boot out the read and write of the list. [15:39.600 --> 15:42.780] So now, let's see the table. [15:42.820 --> 15:49.200] As you can see here, register fee4 has three register objects. [15:49.200 --> 15:55.220] That means in the source code we scanned, fee4 was used three times. [15:55.220 --> 16:04.720] And every time when it was used, we store the present value of register and the function who used it if there is one. [16:04.800 --> 16:09.820] So basically, the whole table is the history of the registers. [16:10.520 --> 16:22.740] So when we finish constructing the table, we then scan through all register objects in the table to check if the native APIs are handling the same registers. [16:22.740 --> 16:28.520] So now, let's see how to use Quark engine to analyze the malware. [16:28.660 --> 16:31.660] Now, let's get back to Kunyu. [16:35.330 --> 16:43.430] In this section, we prepared two malware. One is non-obfuscated and the other one is obfuscated. [16:43.430 --> 16:49.550] And for each malware, we will show how we detect the behavior of the malware with the detection rule. [16:49.750 --> 16:54.070] Now let's look at the first malware. This is a non-obfuscated one. [16:54.070 --> 17:01.870] We will use the rule in Quark engine to detect whether if the malware sends out the cell phone location data by using SMS. [17:02.210 --> 17:06.190] So this is the detailed report of Quark engine. [17:06.190 --> 17:14.250] In this report, the engine shows the detection results of one single malware behavior or you can say one single malware crime. [17:14.770 --> 17:20.750] For example, we try to find if the malware sends out your location data by using SMS. [17:20.750 --> 17:27.690] So in this report, we list out the evidence we found in each stage of the Android malware crime order theory. [17:27.690 --> 17:36.530] And this report shows we find evidence in every stage, which means we have 100% of confidence that the malware has this behavior. [17:36.530 --> 17:45.030] So let's see. In stage 1, permissions like send SMS, access course location, and find locations are requested. [17:45.030 --> 17:51.710] In the second stage, the key native APIs like getCellLocation and sendTextMessages are used. [17:51.710 --> 17:56.350] And in stage 3, we find certain combinations of native API exist. [17:56.350 --> 18:03.790] And in stage 4, we found out that in functions like sendMessage and doBytes, the APIs are called in the right sequence. [18:03.790 --> 18:11.990] And in stage 5, in function sendMessage, we find out that those APIs are handling the same register. [18:12.650 --> 18:21.790] So now let's think, if you are analyzing this malware, and you want to trace the compiled source code to see the evidence, how do you do it? [18:21.830 --> 18:28.670] Our suggestion is you start backwards. That means you start from stage 5. [18:28.670 --> 18:40.670] For example, in stage 5, we know that inside a function of sendMessage, it has two functions that contains the two native APIs respectively, and they are handling the same register. [18:40.670 --> 18:46.810] So you start to locate a function sendMessage in the decompiled source code. [18:47.110 --> 18:52.030] And in stage 4, we know that those two functions are called in the right sequence. [18:52.030 --> 18:59.910] So we can start to find the functions that contains the native APIs and check if they are really called in the right sequence. [19:00.010 --> 19:05.430] The information of the two functions and the sequence will be shown in the next version of Quark Engine. [19:06.370 --> 19:09.650] So now let's look at a real example. [19:09.650 --> 19:12.270] Let's locate the function sendMessage. [19:12.270 --> 19:17.810] And we found out that two functions that contains the two native APIs respectively. [19:17.990 --> 19:20.690] They are sendSMS and getLocation. [19:20.690 --> 19:27.810] And if we dive into the function of getLocation, we will see that it contains native API getLocation. [19:27.970 --> 19:36.050] And if we dive in this function of sendMessage, sendSMS, we will see that it contains native API sendTextMessage. [19:36.050 --> 19:42.490] So the code here means it first collects your cell phone location data and sends it out through SMS. [19:43.270 --> 19:46.130] So now let's dive into the source code of getLocation. [19:46.130 --> 19:55.070] As you can see in the source code, it tries to call native API getCellLocation and returns this information at the end of the code. [19:55.830 --> 19:59.670] And now let's dive into the source code of sendSMS. [19:59.670 --> 20:04.890] Native API sendTextMessage is used to send out the location information. [20:04.890 --> 20:06.650] So quite simple, isn't it? [20:06.690 --> 20:09.690] Now let's look at the second malware. [20:09.690 --> 20:12.310] This is an obfuscated one. [20:12.370 --> 20:22.470] We will use the rule in Quark Engine to find whether if the malware detects Wi-Fi hotspot by gathering information like active network info and cell phone location. [20:22.950 --> 20:27.670] Okay, so as a malware analyst, we read the report backwards. [20:27.730 --> 20:33.950] As you can see in stage 5, there are functions like p.a, addView.c, and af.run. [20:33.950 --> 20:41.710] And those functions have two functions that contain native APIs respectively, and they are handling the same register. [20:41.710 --> 20:51.090] And in stage 4, those two functions are also called in the right sequence in functions like p.a, addView.c, and af.run. [20:51.090 --> 20:59.690] So according to the report, we can see that malware has the behavior of Wi-Fi hotspot detection in three parts of the source code. [20:59.690 --> 21:02.630] And we can pick any parts for further analysis. [21:02.630 --> 21:05.870] So we just pick function p.a. [21:06.730 --> 21:09.830] So now let's look in... now let's see the source code. [21:09.830 --> 21:13.210] Let's first locate the function p.a. [21:13.210 --> 21:21.150] And we found out that two functions that contains the two native APIs respectively, they are ap.a and af.f. [21:21.150 --> 21:29.230] And if we dive into the source code of function ap.a, we will see that it contains native API getActiveNetworkInfo. [21:29.230 --> 21:36.250] And if we dive into the function of af.f, we will see that it contains native API getCellLocation. [21:36.270 --> 21:47.410] So this quote here means, after collecting information from function ap.a and af.f, they sent the information as an input for function am.a. [21:47.770 --> 21:51.210] So now let's dive into the source code of function ap.a. [21:51.210 --> 21:59.870] As you can see in the source code, it tries to call native API getActiveNetworkInfo and return the related information at some points. [22:00.290 --> 22:04.270] So now let's dive into the source code of af.f. [22:04.470 --> 22:10.330] Native API getCellLocation is used to get the cell phone location data. [22:10.330 --> 22:13.550] And this information is processed with some other strings. [22:13.550 --> 22:18.430] And at the end of this function, it returns the strings with the information. [22:18.430 --> 22:30.310] As mentioned earlier, after collecting information from function ap.a and af.f, they used the information as an input for function am.a. [22:30.390 --> 22:33.350] And we noticed one thing. [22:33.350 --> 22:39.830] The function am.a used byte arrayed output string as one of its input parameter. [22:39.830 --> 22:48.190] And we know when seeing byte arrayed output string, it means the function is probably trying to write the data into a file. [22:48.190 --> 22:50.410] This is amazing, isn't it? [22:50.410 --> 22:56.270] So with Quark engine, malware analysis can really boost up their productivity. [22:57.170 --> 23:02.190] Okay, so now I will introduce our detection rule generate strategy. [23:02.470 --> 23:06.690] So why do we need to develop the detection rule generate strategy? [23:07.210 --> 23:15.170] Because to make our engine practical and easy to use, we need to have more detection rules. [23:15.170 --> 23:19.330] However, the speed of rule generated by human is quite slow. [23:19.590 --> 23:25.950] And human generated rules is subjected to his or her experiences of malware analysis. [23:26.070 --> 23:31.270] So we developed a rule generate strategy to boost up the production of detection rules. [23:31.670 --> 23:44.510] And since our goal is to find all kinds of behaviors in the malware, so if we use permissions and native APIs to generate all possible rules, we will have an amazing amount of rules. [23:44.510 --> 23:53.290] After generating the rules, we then use Quark engine to find the intersection between those amazing amounts of rules and the malware we prepared. [23:53.290 --> 23:57.010] In other words, we find rules that match the malware behaviors. [23:57.090 --> 24:03.630] However, this is not a good way to generate detection rules because it's time and resource consuming. [24:03.770 --> 24:07.910] So we developed a seven step generate strategy. [24:07.910 --> 24:15.210] Step one, we curl down all native API information on Android official API reference. [24:15.210 --> 24:20.210] For example, this is the native API information of send text message. [24:20.890 --> 24:26.410] You can see the input parameters, return value and a description of this API. [24:27.070 --> 24:32.070] Okay, step two, we did a little bit modification to our engine. [24:32.070 --> 24:37.890] We ignore the permission checks in stage one of the Android malware crime order theory. [24:37.970 --> 24:45.450] And in step three, we find all kinds of API combination and generate rules without permission information. [24:46.070 --> 24:52.710] And in stage four, we use the modified Quark engine to find intersections of the rules and the malwares. [24:52.710 --> 24:59.150] We call the rules... we call rules in intersection the first stage verified rules. [24:59.150 --> 25:03.930] In other words, these rules need to be verified again. [25:04.450 --> 25:13.550] And since we don't need to generate rules with permission and verify the permissions in Quark engine, the whole process of rule production speed up. [25:13.870 --> 25:17.990] And in stage five, we try to generate rules with permissions. [25:18.130 --> 25:24.790] So inside the intersection, we have first stage verified rules matched with malwares. [25:24.790 --> 25:34.590] We then use the first stage rules and permission in the matched malware to generate rules with permissions, which is the second stage rules. [25:35.150 --> 25:39.730] And in step six, we then use the Quark engine. [25:39.730 --> 25:52.050] Yes, the full function version to find again, the intersection of the second stage rules, which are the one with permission and the malware we prepared. [25:52.050 --> 25:58.410] So after that, for each rule, we label the number of matched malware. [25:58.430 --> 26:05.530] For example, the behavior of rule number one can be found in a hundred malware, etc. [26:06.110 --> 26:13.450] And in step seven, after labeling the rules, we then sort the rules by number of matched malware. [26:13.730 --> 26:19.030] We will review the rules from the highest matched one to the lowest one. [26:19.910 --> 26:23.250] All right, the last part, feature works. [26:24.670 --> 26:28.630] As I mentioned earlier, we still have a lot of things to do. [26:28.630 --> 26:37.770] For example, we need to have more detection rules, and we also need to deal with the .so files and the packed APKs. [26:37.830 --> 26:43.710] And we want to have more features of Dalvik Bytecode Loader, for example, the downloader. [26:43.710 --> 26:51.090] And we also want to apply the scoring system to other binary formats. [26:51.150 --> 26:52.950] Yeah, it is in our to-do list. [26:53.410 --> 26:57.730] And we noticed that API changes in different versions of Android. [26:57.730 --> 27:01.770] So we will also take care of this problem in the next version of Quark. [27:01.850 --> 27:08.050] Oh, we probably would change the core library since Android God is quite inactive recently. [27:08.650 --> 27:10.410] And one more thing. [27:10.710 --> 27:15.630] Actually, we are trying to make Quark itself easier to be integrated to other tools. [27:15.630 --> 27:23.230] For example, users can import Quark as a Python library and output the analysis result as a JSON file. [27:23.230 --> 27:31.590] So now Quark is collected in BlackArch Linux and will soon be integrated to a threat intelligence analysis tool, Intel O. [27:32.470 --> 27:35.310] And there is one nugget that I would like to share. [27:35.310 --> 27:37.710] We work at the limits of our tools. [27:37.710 --> 27:41.030] When new tools come along, new things are possible. [27:41.390 --> 27:43.630] Okay, so that's all for today. [27:43.630 --> 27:49.130] And if you have any questions, please feel free to DM our Twitter accounts. [27:49.130 --> 27:50.310] Thank you.