# Media

url: https://www.youtube.com/watch?v=pTU6O3iua0k
title: Off-By-One 2024 Day 1- Unlocking Automotive Secrets Strategies & Tool for accessing hidden services
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=pTU6O3iua0k",
    "title": "Off-By-One 2024 Day 1- Unlocking Automotive Secrets Strategies & Tool for accessing hidden services",
    "description": "Abstract\n\nDuring car hacking, the first consideration typically revolves around the manufacturer or Tier 1 provider\u2019s hidden services. This spans from common engineer mode applications to deeply concealed mechanisms. However, due to regulatory requirements and increased manufacturer security awareness, high-level privilege hidden services have dramatically decreased. Through analyzing dozens of Intelligent Connected Vehicles, we\u2019ve discovered new tactics for managing hidden services.\n\nIn this talk, we\u2019ll demonstrate multiple methods to access hidden functions and thoroughly analyze underlying theories which involving both traditional and new era approaches. Once we understand the background mechanisms, we attempted to bypass security protections and share our journey, including some bypass skills. Such as use Fipper Zero crack the engineer mode pincode. Upon gaining access to hidden services, we\u2019ll show how to leverage these functions to attain root privileges, execute lateral movement to other Electronic Control Units (ECUs), and gain control of the vehicle.\n\nLastly, I\u2019ll introduce a self-developed graphical hacking tool designed to reveal hidden services. This tool extracts information from firmware and automatically generates a graphical representation of the hidden services relationships. By using this tool, we\u2019ve successfully identified entry paths for many vehicles, including deeply hidden ones.\n\nSpeaker\nPeng Fan (@delikely) is a Security Researcher and Tech Lead working at QAX STARV Lab, focusing on the automotive security. He has received CVEs from Tesla/Cybellum/Bender/etc. Hall of fame of GeekPwn( 2021-2022). Member of the Automobile Safety Research Organization - Qing Ji.The earliest automotive cybersecurity community in China, operating a WeChat Official accounts, has released a panorama of automotive security. Maintainer of Automotive Security Timeline.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2548,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   Hello everyone, my name is Fan Peng from Tianjin's WeSecure Label.  Today I will...  Hello everyone.  My topic is Unlock the Motive Security, Security and Tools for Accessing Hacking Services.  Today I want to discuss hacking services.  What are hacking services?  What are the prerequisites for accessing?  And how to unlock them?  One can use dozens of ECUs.  In the case of country units, the services in the car are like asparagus.  We can only sell a small part of the income used.  Front-end services, which we are able to access the tip of the asparagus.  As a coupler, we can only access all of you, such as the entertainment system,  use a dash camera to record and view road conditions while driving.  We use driver information from the InstaCluster and use ADAS to access us while driving.  Thus, there are still some services reserved for maintainers or debuggers.  It's hard to load internet services to a normal user.  Much more hidden services are under the ice bridge.  Like a framework or operating system and all that.  IPC in ECU, RPC in ECU and RPC between ECUs.  Not only the traditional process system,  there are some complex car frameworks like AutoSAR.  AutoSAR is to correct and explain open and standard software achievements for automotive ECUs.  AutoSAR-AP for the process system.  AutoSAR-CP for simple microcontainer units.  AutoSAR only defends the standards and doesn't implement them.  The software supplier implements them by themselves.  There are many hidden services inside that that are worth to explore and do some deep research.  Here are three entrances to access these hidden services.  The first one is a disk environment to enjoy the best head units.  The car service is the main entrance.  For Linux-based head units, we will use the VLAN while the disk environment.  Some other uses are Qt, Twilio and QSCS.  The second one is a Spark interface.  For Android, we will use ADB.  For the process system, we will use SSH.  The QSCS is usually used for the instructor cluster or ADAS.  We usually use Qualcomm to debug.  The second one is a hardware interface, such as UART,  which is usually used for the SoC.  The GTAC is used for the MSU.  The ODB is used for the home card.  The intelligence context has a huge screen,  which serves as the main entrance point for user interaction.  Each cluster manufacturer has its own human interface, called IVI.  Some IVIs are based on Linux, some are based on QSCS.  But most are based on Android.  Android launches allow car makers to customize their home screen,  start new applications, make a home call, and perform other tasks on Android devices.  This custom essential context look and feel of the home screen and app journals  provide users with a tailored experience.  However, there are simplified differences in customer limited.  Each orange equipment manufacturer builds its own launcher.  With that, in a unique user interface,  one major difference is that the standard setting app is not displayed on the launcher.  Instead, there is a specific setting.  The setting includes a function for setting up a list of workers  who use system information and upgrade the firmware.  However, its unique search capability only allows the user to use the extension function.  Typically, the developer mode can't be enabled by the user.  Here is a car maker using the launcher's source code lead framework.  They have a big difference with each other.  They are based on Android launchers from the first generation to the third generation.  And some car makers built by them own some limited car launchers.  Unlike mobile launchers, some car launchers don't display the third-party placing on the desktop  such as the application named Joy2.  On the left side, we can see in the launcher's desktop.  But on the right, we can't get it.  Some systems built in AP are hidden from the launcher.  What happened?  I tried to figure it out.  I compared two applications.  The left one is the display on the launcher.  The right one is hidden from the launcher.  We found that in the Android manifesto, there is an interface category.  If the category is a launcher, it will show on the top-level launcher.  Without this category, it will be hidden.  I tried to build an app.  There are two activities.  The first one is the main activity.  The second is the third activity.  After we compared and installed into the car head unit,  there are two icons displayed on the launcher.  An application can display multiple icons on the launcher.  When an activity has a large category, it will display an icon on the launcher.  If no activity on an application has a large category, it will be hidden from the desktop.  We analyzed the Android launcher.  In the Apple filters, we can see an error.  Filter components.  This error defines the error.  If the package name is in this list, it will be hidden from the desktop.  But car makers almost never use this way.  They often use their own way to hide the apps.  They maintain their own whitelist.  This whitelist contains four lists of applications.  This will show on the launcher.  Sometimes, Apple applications are flawed again.  For example, this Apple engine mode.  If the package name is in this filter, it will be filtered.  Sometimes, we can make hidden apps appear on the launcher using system build functions.  For example, we found a hidden page such as developer switch.  When we click here, we are setting the Android launcher developer to true.  We can enable hidden apps to be visible on the launcher.  The function handleValueChanger is nested to the setting.  It can add more hidden pages to add desktop applications.  When we click more apps, we will have the ability to access the hidden apps.  Is there any way to see the hidden apps?  We can use our current launcher that doesn't fit any apps.  By now, we can access system downloads, web user tests, the launcher, or the native settings.  And other hidden apps with the default icon.  To access more hidden services, the first step is to break down the launcher and get free access to any service.  After all the steps are done, I have concluded that there are 18 methods to unlock hidden services.  Unlock hidden services based on the generation in a spare place, like MoneyClick or Lampress.  Some use password protection.  In the next session, we will discuss how to break it down.  The third method is a direct code.  This is another type of password protection.  The next one is voice control.  This is a new type of entrance.  The next one is to use USB over Diagnostic for command use.  The last one is to use Manicurist to call the apps.  Click is defined by MotionEvent.  MotionEvent describes motion in terms of action code and set of action values.  The action code specifies the state changes that occur, such as a pointer going down or up.  The pointer values viral position and other movement properties.  Press is acting down, release is acting up.  Lampress on the software is an example.  It will check the current time to test if the time less than 2 seconds will reset.  If bigger than 2 seconds, it will enable the hidden service.  As we know, Android can click on Lampress to open the developer mode.  Here, it defines the MDU headcount.  Initial value is 3.  Once we click, this value will decrease.  When it is equal to 0, we will show the developer mode enabled.  Sometimes, the click release is special.  We need to find the errors.  Use X and Y if 0 to 18.  X and Y if 0 to 18.  It is easy to find.  It is simple.  Red color.  Now, this color.  As we know, Android uses a series of panic codes.  There are 6 panic codes to show MEI.  Similarly, OEM or other vendors use Android-safe code to create hidden service.  Like this.  With this interface action, Android provides telephone security code.  To create code, we can use the direct app input panic code to call this.  They can get the URI from the intent, then check if it matches the defined URI.  Provide the Android-safe code to start the hidden service.  This is to start the hidden service.  However, some don't use Android-safe code URI.  Instead, use getTextString to check if it matches the defined code.  In the application Bluetooth, we can check the string between getString value to a predefined value.  We can look at this.  If the TLAG code equals to equal to 46, we will start the password activity.  Otherwise, enable the ODB activity.  There are 4 ways to use Android-safe code.  First is DARP.  Use this URI of Tails to open this hidden service.  Another way is to use DeepLink.  It has a different schema.  This uses Android-safe code.  If you have any VHL access, use M to open the hidden service.  Use Action, AndroidActionView, and UserData as DeepLink's URI.  The last one is to use BroadRaw or WebView to access.  I will discuss this in detail in the next section.  How to scan this code or other code?  We can use some open-source applications, such as SecretCode.  It allows us to scan the secret code available on the device through the DARP app.  But in some situations, the car doesn't allow to install any other apps.  We can use the register to get the secret code without the need to install the app.  Nowadays, WAZE is used more frequently in various services,  such as Control Air Conditioning or Open Windows.  Surprisingly, we just speak to the WAZE assessment  and open a head page in ASP.Adapter.  It will check the WAZE command, engineer mode, and open the engineer application.  Currently, it uses keywords to match with the use of GPT to enhance human interface capability in car WAZE assessment.  There is a similar risk to proposing a tag, which can influence unsafe operations.  The next one is to use USB to open the head service.  Maintenance engineers use commercial USB keys without the physical USB keys.  Others can access cars in their system.  However, if a key is lost, anyone who can access any car uses this security bug method.  We also encountered backdoors using USB stick plug-in.  The system will check the shift-swipe-drop with the speaker of the LAN.  If there is a shift-swipe-drop in the USB stick, it will automatically execute this shift-swipe-drop.  The next one is UDS routing.  We use UDS routing to open the head service.  UDS is a unified diagnostic service specified in ISO 14228 standard.  It is a prototype used in automotive infrastructure for vehicle diagnosis and programming.  The routing control service is used by the client to execute a defined sequence of steps  and obtain any related results.  Enabled head service sometimes requires a security access.  We found that we can exclude the manufacturer's own custom features.  First, we need to change to the extension session.  We use the diagnostic country session.  It is the 1.0.0 session.  After we enter the extension session,  first, we need to get the unlocked algorithm.  We need two algorithms.  The first algorithm is the set.  We can use the access 0.1.0 to get the set.  The second algorithm is the circuit.  We need to read it from the DID.  Using the 2.2.0 session,  we can read the UDS security concept.  We use the 2.7.0 security access to get the set  and use the set and security concept to calculate the K.  After we unlock this,  we can use the routing control to use this head service.  Here is an example.  We found that some car makers use routing control to open the SSU debug port.  Here, we can run CS5 jobs.  This function name is UDS dialog start up SSU.  We can look at this ADAS diagram.  This is the SSU called by UDS routing start up request.  The 18 unlocked methods are commonly used in the head service.  However, I have discovered three interesting and special methods.  First, users prefer to break down the password protection service.  The second one is to scapegoat to the native setting.  The third one is users blink to enable the head service.  We can test one card.  We found the engine mode.  We input the password.  When we input for digital,  it will show error password.  Only for digital password,  I try to if we can brute force.  It's hard to brute force manually,  but Beta USB may help us.  Before using Beta USB,  we must check whether the head user can use the extension devices.  Because some cards are limited to use extension devices.  I try to insert a wireless keyboard.  Insert into a USB port.  And it works.  Then, I use Beta USB to correct the password.  Here I write a little code.  First is the password.  Use the string.  And enter a password to check the password is right or wrong.  The backspace clears this error password.  And delay 5 milliseconds to the next loop.  Finally, we get the correct password  and unlock the engine mode application.  Here we use the fingerprint to correct the password.  We success to get the password and enter the engine mode.  The second one is escape to network settings.  Press the content in the press policy.  Show options like copy or share.  Selecting share, going to Bluetooth page.  There is a search icon.  Here.  Check if it can jump to network settings.  By inputting a specific word,  we can jump to system settings and develop options.  In the develop options,  we can open adb user to USB debugger.  The third part is deep link.  As most early,  Android and SQL codes are a type of deep link.  However, it is difficult to bypass restrictions.  We found an interesting filter.  And we intend to categorize it as bloatable.  Thus, we can trigger it from the bloatable web view.  Here we find the hidden service  to trigger the adb enable.  The deep link with this category is bloatable.  And the HDMI unit host is a separate code.  And the port is line 527.  And the pass is adb active.  We can click the URL to open this hidden service.  To test, we can open with bloatable.  We build a test app with intent filter.  Android intent category bloatable.  And declare the URL.  First, we use web browser to open it.  And it is successful to open the adb server.  First, we test in web browser.  After we click the Android UI,  and to the menu,  open the adb and jump to the test page.  Then, we try to use web view to verify it.  And it works.  Finally, we try to enable real car.  And we successfully enter the adb activities.  Use the same way,  we found a more interesting deep link page  to access the log, hidden activities,  open web case and console settings.  Here we use web view.  Because some cars don't have bloatable,  but usually have web view.  We have successfully used this method  to open hidden service in some cars.  Due to the confidentiality,  we can't show real case demonstration here.  After unlock the door and enter the inner system,  we discuss more interesting and useful things.  I have six four-tact example.  The first one is disabled activity.  The second is the property.  The third is the permission.  And the last is test boundary.  Disabled activity,  when the active event Android Android 2.4,  the activity can't be used.  We discovered a large number of hidden service  enable activities through scanning.  We can access many important and sensitive results.  Through this, we can access and obtain  many sensitive interfaces.  The second one is the property.  We know the Android automotive hack property  is only 129.  We can use this to view Windows partition  or to look at Windows.  But we found other car makers  will defend their own hack properties.  Some cars have more than 2,000 hack properties.  They can use the property to get solutions  such as the cabinet door open station  or to read data from the UART  or to get the UART SSID password.  Also, you can use the property to send some commands  such as MCU control.  Usually, to control the car,  we need to send the data through the MCU.  The other library,  we choose the property  we can directly send the raw code.  Sometimes, the cars use security storage.  We can't get sensitive data.  We can use this property  to write PKI or to read PKI.  The third one is the normal property setting.  The property usually has the permission  to limit other users to use.  But the car makers usually don't set the permission  to their own hack property.  Then, any app has the ability to use this  such as opening the charging guard  to use the setting board's property.  The second is the test binary.  The test binary may be available in RISC-V.  Android automotive uses WCAG HAL tools  to read and write properties.  The WCAG HAL tool is actually associated with Android Health.  This tool is used to preview or test  and interact with WCAG HAL  while acts as a bridge between the Android framework  and other WCAG HAL hardware,  such as using WCAG HAL to open the air conditioning  or standard engine.  Due to the limited permission,  ordinary applications can't control WCAG HAL.  If WCAG HAL is not found,  we can try to find standard applications  such as OEM cards.  They can use the set property like WCAG HAL tools.  To unlock the hidden service,  we can use various methods  defined by the card makers,  such as non-precise dial code, voice commands,  and other technologies.  Alternatively, we can automate the system and app's features  by path restrictions,  such as escaping to settings  or clicking the link to open hidden service.  After accessing the hidden service,  we can find hidden apps, disable activities,  and explore other valuable apps to dig deeper.  Using background services and RPCs,  we can collect data,  correct unused issues,  and automate takeover the card.  HAL is a real case,  demonstrating for stable to unlock hidden services to control cards.  First, we get some familiar from this work.  After we analyze the very deep link  with the blabber observable categories,  through click the deep link,  we start the hidden service engine mode successfully.  After we analyze the engine mode application,  we use overflow to get the UCCL.  At the first step,  we analyze the application to export data to USB.  We found this log to export  After the file is downloaded,  we get the file word.  After analyzing the file word,  we found the vulnerability,  and we use the vulnerability to get the ADAS CL.  In the ADAS,  we can find that all human cards work as a health tool  to use the compass to control the card.  HAL has plenty of services with complete solutions.  Think about the relationship you will challenge.  In order to help understand what happens and how data flows,  I try to visualize this relationship  and make it easier to analyze and understand the interaction with the system.  I built this user diagram to show the relationship  between Android application activities and services.  It also works nicely to use our binary files,  IPC for internet ECU communication,  and RPC for communication between ECUs.  Here is an example of the flag of our graph,  our ABD coin relationship.  The IPCs are exclusive from the system, data, and Windows products.  Each node perpendiculates on an IPC,  and each arrow represents the flow of data,  indicating which application can call which.  The application layer's IPC frequency calls the Android underlying service frequency.  The tool provides two modes.  One of four data includes the prefix android.android,  and the other didn't show Android's native-based application.  More consistent display,  able to spend less time to analyze the core relationship,  and this is for all of you.  You can also double-link to display only the core relationship between the two applications.  Timely use concerns include how to start the engine mode.  Here are two arrows pointing forward to the engine mode.  One from the engine mode index is one part from the engine mode app.  There is only one way from phone 3 to engine mode.  Using this diagram, we can easily find this entrance.  Only the entrance, we can use phone 3 to open the engine mode application.  As we mentioned before, it may be used as a secret code to access the head service.  Using this diagram, we can not only identify the entrance,  but also virtually observe the data flow.  For example, the OUI exchange data with the four applications.  Open web service config and notification center library is OTA service.  When hunting for bugs in OTS,  we have an overview of the app relationship,  help us quickly and easily understand this connection,  make it easier to find vulnerabilities.  The project's source code will be available on the GitHub.  It will take some time to detach this from the project,  but I will complete it as soon as possible.  Thank you for listening.  Sincerely thank you to our neighbors for the invitation.  Thank you, Peng Fan.  I would like to extend to the floor anyone with any questions.  Thanks.  My question is regarding the decompiler that you used,  so particularly when you decompiled the classes to DEX.  Which decompiler did you use?  No, which decompiler when you decompiled the classes to .DEX, the DEX file.  Because the output was very clean.  It had a bunch of intermediate variables.  I think it was like slide nine.  We used some application tool,  or less the source code.  We used some open source,  like JEDX or like this app to figure out the data workflow.  Thank you.  Any other questions?  Yes.  I'm just curious about the brute forcing part.  How safe is it to brute force?  Have you bricked any card by brute forcing?  Brute forcing the password.  Brute forcing the password?  Yes.  We found that in some situations,  the password is very good.  We found that when we input for digital,  we will show this type, the password error.  And then we can limit it to try times.  So we use the FlipZilla or BetaUSB to correct this.  If the password is conflicted,  we can't proof this.  But if we can get a firewall,  we can to analyze the binary and get this password.  Sometimes the card is conflicted,  provided by the tier 1 or tier 2.  We can analyze tier 1 or tier 2,  to tell us to conduct some type.  They use the same way.  So it's just time-deviant protection, is it?  So there's only a limited number of attempts.  You can't have unlimited.  In the old hack,  the computer didn't take this account.  If not, then let's thank Peng Fan again,  for his very insightful talk.  Thank you Peng Fan.  Thank you.


url: https://www.youtube.com/watch?v=tOwSet1RVkU
title: Off-By-One 2024 Day 1- Ghost in the BLF:A 2 year journey of chasing in the wild LPE exploits
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=tOwSet1RVkU",
    "title": "Off-By-One 2024 Day 1- Ghost in the BLF:A 2 year journey of chasing in the wild LPE exploits",
    "description": "Ghost in the BLF: A two-year journey of chasing in-the-wild LPE exploits in Windows CLFS\n\nAbstract\n\nSince October 2021, we have been continuously chasing the latest in-the-wild Windows CLFS (Common Log File System) LPE exploits. During this process, we captured two in-the-wild Windows CLFS 0days and at least seven in-the-wild Windows CLFS 1days.\n\nMeanwhile, through variant analysis of the itw exploits, we identified two new CLFS vulnerabilities and reported them to Microsoft. Interestingly, two of the captured 1day exploits utilized the vulnerabilities that we discovered through variant analysis.\n\nIn this talk, we will share how we are using the combination of \u201cthreat hunting\u201d and \u201cvariant analysis\u201d to assist Microsoft in patching four CLFS 0day vulnerabilities (two in-the-wild 0days and two independently discovered 0days).\n\nWe believe that the approach combining \u201cthreat hunting\u201d and \u201cvariant analysis\u201d is more effective than traditional defense methods, and we want to share our practical and insights into this process: why we selected CLFS vulnerabilities, how we chased in-the-wild CLFS exploits, how we analyzed captured vulnerability exploits, and how we conduct variant analysis. At the end of this talk, we will incorporate the latest findings to give some insights on the in-the-wild Windows LPE 0days trends.\n\nSpeakers\nQuan Jin is a security research expert from DBAPPSecurity WeBin Lab. His interests are vulnerability research and itw 0day hunting.\n\nHe has received more than 40 CVE acknowledgments from Microsoft/Adobe/Apple, and has been listed as a MSRC Most Valuable Security Researcher for three years(2020-2022).\n\nHe once spoke at Bluehat Shanghai 2019, HITB2021AMS/HITB2023AMS and BlackHat USA 2022/BlackHat Asia 2024.\n\nYingqi Shi is an undergraduate senior majoring in Computer Science, currently serving as a security research intern at DBAPPSecurity. His main research areas include binary analysis, vulnerability discovery & exploitation and reverse engineering.\n\nHe excels particularly in reverse engineering. He is a core member of the Nu1L Team, achieving excellent results in numerous top-tier CTF (Capture The Flag) events both domestically and internationally. He once spoke at BlackHat Asia 2024\n\nGuoxian Zhong is a senior security engineer at DBAPPSecurity WeBin Lab. His main research areas include binary analysis, reverse engineering and vulnerability discovery & exploitation. He once spoke at BlackHat Asia 2024.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2170,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   Hi, everyone.  We are happy to be here at the BionConference.  Today we are going to talk about Ghost in the DLM, a two-year journey of testing in  the wild LPX road in the North Commonwealth Fire Sector.  My name is Chuan Jin.  They are my two team members, Xi Shi and Guo Xianzhong.  We are from BBATP Security Weaving Lab.  This slide outlines the key points of our presentation.  First, we will talk about our journey of testing in the wild LPX roads in the North Commonwealth  Fire Sector.  Second, we will review a Pandora's box of the North Commonwealth Fire Sector X roads  and compare them with the work of other vendors.  Third, we will discuss some samples that other vendors have overlooked.  Finally, we will provide some insights into the transport in the wild Windows LP0 days.  This page lists some previous researches on Windows Commonwealth Fire System, including  Death Note of Microsoft Windows Kernel by Ken Lam, Commonwealth Fire System Internals  by Alex.  Tracking the Commonwealth Fire System by 360 and Windows Commonwealth Fire System and  file X roads used by ransomware operators by Kaspersky.  Similarity with these words will help you better understand our talk.  Next, we will divide our presentation into five parts.  The first part is Start, where we will discuss how we began this work.  The second part is Hunt, where we will explain how we hunt the first eight Commonwealth Fire  System X roads.  We will provide a brief overview of each X road, including basic information and the  vulnerability root cause.  The third part is Analyzing, focusing on our painful experience in analyzing the first  Commonwealth Fire System X roads and how we developed some tools to speed up the analysis.  And share two more unpublished Commonwealth Fire System X roads.  The first part is Variant, where we will share two Commonwealth Fire System vulnerabilities  that we discovered through variant analysis.  The last part is Summary, where we will provide the relations between different Commonwealth  Fire System X roads and make a summary.  Now, let's step into the Start section.  We began our journey by catching the first Commonwealth Fire System X road in October  2021, which triggered a YARA report we wrote for Pipe Tribute.  This X road, with its CV under, achieved control flow hijacking by modifying the P  container pointer.  For more details about this step, you can refer to my Black Hat USA 2022 presentation.  Here, I want to highlight the P container member, which is illustrated in a diagram  from a blog of Kaspersky.  This diagram is easy to understand, so I will close it here.  P container is a key pointer exploited by the first and all subsequent Commonwealth  Fire System X roads we caught.  All the X roads we caught focus on how to modify this member.  So, let's see how the first X road modifies the P container.  It modifies the P container by performing a 1-bit flip inside the Commonwealth Fire  System logSVB physical FlashMatterData function.  Through this operation, it changed 1-bit of an offset, causing the Commonwealth Fire  System driver to load a fake P container.  In April 2022, several Commonwealth Fire System vulnerabilities were reported, including one  reported by NSN and CrowdStrike.  Additionally, the research paper on 360 attacking the Commonwealth Fire System was presented  at Black Hat Asia 2022 this month.  At that time, we realized that more X roads in the Commonwealth Fire System may appear  in the future.  When we realized this, we began a serious hunt journey.  So, how do we better hunt these X roads?  First, let's review how the first X road was caught.  It was detected by a YARA work we wrote for the pipe tribute technique.  For more details, please refer to my presentation at Black Hat USA 2022.  The Chinese philosopher Lao Tzu once said, the way backs one, one backs two, two backs  three, and three backs all things.  By carefully studying the first X road, we can quickly find the second and the third.  So, how did we analyze the first X road?  We studied it from multiplying dimensions, such as code similarity, PVB paths, X road  techniques, and strings.  Additionally, Steve Jobs once said, stay hungry, stay foolish, means one should remain  humble and eager.  Therefore, we actively collected and carefully studied information about Commonwealth Fire  System vulnerabilities disclosed by other vendors.  Another month passed, and we caught the second Commonwealth Fire System X road, which also  triggered the pipe tribute work.  This stamper was caught in May 2022.  One interesting aspect of this stamper is that its PVB paths indicate that the author  believed he was writing an X road for CVE 2022-24521, but he's not.  This X road was labeled by Kaspersky as X road 1.  Let's take a look at where the P container point is modified in this stamper.  It's still within CLFS, not CVE physical flush mentor data, but this time it's using  The third Commonwealth Fire System X road we caught was in a wild stamper of CVE 2022-24521.  This was the real CVE 2022-24521.  The vulnerability origin from a lack of proper validation on the signature's movie set of  CLFS log block header.  Let's see how the stamper tampered with the P container.  It modified the P container within the CLFS encode block function, and the CLFS encode  block function was called by the CLFS base file persisted write metadata block.  In the same month, we also caught another in the wild Commonwealth Fire System X road.  This time is a really zero day.  The CVE number is CVE 2022-37969.  This stamper also hit our pipe tribute row and many other rows.  The X road code of the stamper used a different technique from the previous stampers.  It employed the NTSC set access state generate matching and the CLFS earlier LSN function.  For those interested, this galler had published two high-quality blog posts you can read there.  Let's see how the stamper modified the P container.  This time it was done in CLFS base file persisted a log symbol by using memory set.  It particularly zeroed out the P container.  One month later, we caught another new Commonwealth Fire System one day X road, which was also  detected by the pipe tribute row.  We couldn't identify the CVE number for this X road.  But what's interesting is that it introduced some new X road techniques, this including  hijacking virtual function codes in CLFS base file persisted check secure access and using  functions such as CLFS, MGMT to register management client, NTPOFX processor notification  and NTRK or clear read.  Kaspersky had also discussed this stamper in their blog labelled as X road 2.  Readers interested can refer to their blog.  Let's see how the fifth stamper modified the P container.  This time, it returned to the CLFS log FCP physical flush meter data function, but used  the F attributes instead.  Another month passed and we caught the sixth CLFS X road, which also didn't have a CVE number.  The X road technique used in this stamper is similar to the previous one.  Kaspersky had also discussed this stamper in their blog labelled as X road 3.  Let's see how the stamper modified the P container.  This time, it was still within the CLFS log FCP physical flush meter data function, but  it used the LSTM restart number.  By summarizing the strengths and X road techniques of different X roads, we can clearly identify  two different developers.  We can roughly categorize the first and the top of thirds on the developer A and the second,  the first, the fifth, the sixth and a later one on the developer B.  The next stamper we caught was CVE-2023-28252, but we decided to first discuss in the wild  sample of CVE-2023-23376, which we discovered when analyzing the CVE-2023-28252 X road.  This is a zero day that was caught by Microsoft itself.  Due to Kaspersky had provided detailed information about this vulnerability in their blog, and  they labelled it as X road 4, so I won't talk too much about this X road here.  Interested readers can refer to their blog.  The eighth X road we caught was CVE-2023-28258, another in the wild zero days.  It was reported to Microsoft by us, Kaspersky and Mandiant.  Kaspersky has also discussed this X road in their blog, labelled as X road 5.  Again, I won't talk too much about this X road here.  Interested readers can refer to their blog.  After briefly sharing the eight common log file system X roads, we can move to the analyze section.  First, I'd like to share with you how we analyzed the first common log file system X road.  At that time, we were completely unfamiliar with Windows common log file system and BLF file format,  and there were few materials available for them.  To analyze the first X road, we did a lot of debugging and reverse engineering, made us exhausted.  Afterwards, we started developing a 010 enter template for parsing the BLF file format.  With the template, analyzing the BLF log files became much easier.  This greatly accelerated our analyzed speed.  In addition to the 010 enter template, we also wrote a common log file system structure header file  that could be imported into Header.  After importing the header file, reverse engineering of the common log file system driver became much easier.  This greatly facilitated our analysis of common log file system X roads.  Next, let's discuss a few questions.  The first question is how to define whether a sample is a 0-day, 1-day, or N-day.  The second question is how to determine the root cause of a common log file system vulnerability.  The third question is how to classify a new X road under a specific common CDE.  For the first question, we used the simplest method, creating three environments to distinguish the three types of X roads.  For the second question, we typically used the 010 template to parse the fields of the tampered BLF file  to locate the files that facilitate the identification of the vulnerability's root cause.  For cases where 010 template is not enough, we will use reverse engineering and debugging for further confirmation.  During the analysis process, we also discovered some interesting samples.  For example, in the wild X roads of CDE-2023-23376 and CDE-2023-28252 at Packard and to evade detection,  some samples are also obfuscated, like the 28258 in the middle of this slide.  Additionally, there are some samples that do not work properly or cause a BSOD after running.  Next, let's look at the 9th common log file system X road, which we caught in November 2023.  Interestingly, its compilation time was also in November 2023, but the corresponding vulnerability was patched in January 2022.  The code style of this sample is significantly different from the two developers mentioned before,  and the code quality is a bit low. After running the sample, the winlog process will crash.  Additionally, this sample is not compatible with the Windows 11 operating system.  All signs indicate that this sample was written by a non-professional developer.  This sample has not been publicly disclosed before.  Let's see how this X road modifies the P contender.  This sample also modifies the P contender when assigning the query time number in the CLFF logFCB,  physical flush mental data function. It's in the same point as I mentioned in the second X road.  In the same month, we also caught another common log file system X road.  It is a vulnerability that was patched in September 2022.  We found that this sample's X road techniques are basically the same to the second X road.  So it can also be considered as being written by the developer B.  This sample has not been published disclosed before.  Next, let my partner Yingqi Shi explain how to look for the root cause of this X road.  Since we have many malicious samples, the next question is how to analyze the malicious exploit.  We must know how they do, how they construct the P of file.  Let's look for root cause of about 10 exploits.  The first thing we do when we get a malicious sample is to reverse it.  But unfortunately, our sample has been obfuscated by counterflow.  There are too many junk instructions, too big stack frames, and this assembler is too slow.  How to solve it?  Let's try to think as an exploit developer.  We allocate memory to store our shared code locally.  In Windows, we use virtual log generally.  So we look up import tables and try to find the code.  You can see our guess was right.  Next, we set a hardware breakpoint in the allocate memory region.  You can see interrupt success.  They still use decontainer to hijack the counterflow and elevate their privileges from user level to kernel.  Then, we have a question.  Where does decontainer change?  After some reversing works and debugging, we noticed the function writeMeetDataBlock  placed the decontainer in the class instance into the file count block.  Let's see where decontainer comes from.  As you see, container context contains decontainer.  Context comes from the function acquireContainerContext.  Now, let's see more about this function.  In this function, it gets the base log recorder and retrievals named rgContainers according to the index.  rgContainers is an array of the container symbols offset.  Then, it will call function getSymbol to get container context.  New question arrives.  Where does the container symbol change?  Before we continue our question and answer, we must know what symbol.  What is the structure of symbol?  You can see the picture on the screen.  It's still referring from Kaspersky's log.  As you see, this structure means hash symbol and has field named cbOffset,  means count of bytes offset.  This offset points to all contexts, including client and container.  And cfS driver according symbol offset to get context.  The function symbol tells us we have another function to hash symbol.  Continue.  According to the input tables and reference code,  there are function chain called by addLogContainer.  That means our idea is right.  We can call function aLogSymbol to create a new symbol.  Let's see that.  It's getting more and more interesting.  After reading, we can see that the initial symbol has part cbSymbolZoom.  That offset of symbolZoom.  I think it can be called symbol cursor.  It's offset of nextSymbolOffset.  That means it's offset to all of all exist symbol ended position.  This function initializes the memory region to the symbol according to cbSymbolZoom.  You can see my blue comment marks the offset in my comment block.  Remember it.  Be careful.  If you use format template path file, you will be stressed.  So you can see on the screen, I have marked the points corresponding to cbSymbolZoom.  Clamp context overlaps with container symbol.  It's magic.  OK.  Next, let's move on.  Back to Kotlin.  You can see the highlighted code.  It's construct structure of cfsHashSymbol.  This structure includes cbOffset.  Remember it's offset of context.  OK.  Back to Kotlin again.  We create symbol after calling and symbol next function.  AddContainer will use cbOffset and locate to symbol and read offset of context.  And the key point, setToClampDistance will end rgContainers.  Do you remember that a few minutes ago, I mentioned the rgContainers in function acquireContainerContext.  Let's see it again.  Yeah.  We use cbSymbolZoom to control offset of symbol.  So when we call acquireContainerContext, the driver will get valid container context under our control.  Back to the code.  It's then will call to the function named writeMeetDateBlock.  Does it look familiar?  We are back to the beginning.  So now, we control driver to write a new container context as a special case.  The last question is, where modify the container in the structure of container context?  In order to answer this question, we notice the function, flashMeetDate.  As you see, this symbol modifies the container.  cbOffsetDriver restores client context from class instance.  By the way, the reason I mentioned the restore also means that there must be backup.  So in this case, I omit backup part.  The corresponding field view comes from raw file con cloud in fact.  The modification occurs when the LSN last and LSN restart member was assigned.  Finally, you can see the container has been modified.  At this point, we have synonymously identified the root cause of this vulnerability.  Next, I will get my under-training and you shall read the rest of our presentation.  After discussing the 10 in the wild common log file system exploits, we will now talk about variant analysis.  Why variant analysis is important?  I think this slide by Manny Stow gives us a reason.  How do we conduct variant analysis?  I think it can be divided into two situations.  The first is when the vulnerability itself hasn't disappeared,  but a patch accidentally prevents the triggering of this vulnerability, causing the exploit to fail.  A typical example is CVE-2022-24481.  The second is when the developer seems to understand the root cause of the vulnerability and fix the bug,  but they have not completely fixed or made a mistake.  A typical example is CVE-2022-35803, which we found by auditing the patch for CVE-2022-24481.  Let's first look at the example of CVE-2022-24481.  A key point of this exploit is that there is a 1-bit flip at this location.  However, in the September 2021 patch, an added validation accidentally blocked this vulnerability.  The patch only checked the value of ClientContextOffset,  to make sure it couldn't be less than 3068.  So what if we construct a ClientContextOffset that is greater than this value  and make the ClientContextOffset point to a forward container context?  But after some simple modification, a new 1-bit flip was born.  And this leads to BSOD.  Now we can see the familiar BSOD again.  This variant is CVE-2022-24481.  And now let's look at the example of CVE-2022-35803.  This vulnerability was discovered while analyzing the patch for CVE-2022-24480.  In the April 2022 patch, the Common Log File System driver added a new function  CLFSBaseFileValidateRgOffsets.  Due to this patch, the method of directly modifying the ClientContextOffset was fixed.  However, there was still no check for CIDNode.ctype.  Therefore, we only need to set the CIDNode.ctype file  of a ClientContext to ContainerContext to bypass this patch.  Lucky Yu has written a wonderful blog about this vulnerability.  Anyone interested in this case can read his blog.  By the way, the in-the-web-exploits mentioned in Lucky Yu's blog  is actually the second exploit discussed in this talk.  From the figure, we can see that by changing the type of different contexts,  we successfully hijacked a function point to a non-executable memory, triggering a BSOD.  Finally, let's briefly summarize this presentation.  From October 2021 to November 2022,  we caught 10 different Common Log File Systems in the wild exploits over 2 years.  The table shows the CVE numbers of these exploits,  their corresponding neighbors by Kaspersky's blog, and their hashes.  During the journey of tracking Common Log File Systems,  we have caught two Windows-in-the-wild zero-days  and independently discovered two Common Log File Systems zero-days through variant analysis.  All these four vulnerabilities received acknowledgments from Microsoft.  And finally, combining with recent observations,  we can predict the trends of Windows-in-the-wild exploits.  We believe that the battle with Windows Common Log File System is nearing end,  while vulnerabilities in Desktop Window Manager and other models will gradually increase.  Thanks to these guys for assisting in this journey.  And bingo, it's another stage.  Thank you for listening to our presentation.  Does anyone have any questions?  Thank you for the presentation.  Can you open the floor for any questions?  Do you think there's a systemic issue with the CLFS,  or was it just bad at the start?  Do you think there's a systemic issue?  In the sense of, is there a methodology in the way that it's implemented  that creates a series of security issues,  that they're just sort of putting band-aids over,  or was it just bad at the start?  Is there something systemic in the way that it was built that leads to security issues?  Okay, due to my English,  your question is a bit complex to me.  And you can ask under this stage,  and we can talk one-to-one.  Oh, okay.  Because I have to think about this question.  I think when Microsoft developed this common log file system driver,  they made some mistakes on the desire level.  Actually, many of the exploits were successful  due to this peak and end pointer.  But if you do better in the desired level,  I think they can prevent this at a very early time.  But for now, Microsoft,  they only fix every case,  and they never disable this driver  in order to introduce some implications for this question.  But the good thing is that these exploits have a line like this.  So I think this battle with the common log file system is near the end.  Because in the past six months,  we have called two Windows Desktop Manager zero days.  So I think maybe the target now pays attention to DWM and other models.  I think these models will have a trend like this.  There's another question.  Why do you say that the battle with CLFS is nearing its end,  and why do you see Desktop Window Manager being more vulnerable over time?  Okay, I have just answered this question, and I'll answer it again.  From our presentation, you can find that  the first eight common log file system exploits caught by us  happened in November 2021 to November 2023.  And the last two were caught in November 2023.  If you draw a picture,  by time and the catch time,  you can figure a picture like this.  So based on it,  we can predict that the battle with common log file system is near the end.  And why do I think Windows Desktop Manager vulnerability will have more in the future?  Because in November 2023 and in April 2024,  we have caught two DWM in the last zero days.  And due to the complexity of the Desktop Window Manager model,  it's DWM code, not Dell,  or the 132k model,  we think there are more vulnerabilities under this model.  So I think maybe this is just the start of the next battle.  Any more questions?  Looks like that's about it. Thank you very much, guys.


url: https://www.youtube.com/watch?v=9rt9ErQKnf8
title: Off-By-One 2024 Day 1- Exploring WebKit’s Just In Time Compilation: Vignesh S Rao
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=9rt9ErQKnf8",
    "title": "Off-By-One 2024 Day 1- Exploring WebKit\u2019s Just In Time Compilation: Vignesh S Rao",
    "description": "Abstract\n\nJIT compilers have been the subject of numerous vulnerability discoveries. This is due to the nuances of optimization phases and their potential to introduce subtle bugs. This talk aims to unravel some key optimization phases in JavaScriptCore, WebKit\u2019s JavaScript engine that powers Apple Safari.\n\nThe focus will be mainly on DFG intermediate representation and how optimization phases on this can give rise to vulnerabilities.\n\nThrough specific examples and case studies, we will examine vulnerabilities resulting from logic errors in the compiler. These examples will showcase the real-world impact of optimization phase vulnerabilities, highlighting their severity and potential exploitation scenarios.\n\nSpeaker\nVignesh Rao is a vulnerability researcher at Exodus Intelligence. He is currently focusing on bug hunting and exploitation of web browsers, with specific focus on JavaScript Engines. He loves anything system security related and has researched multiple userland and kernel applications before especially in the MacOS/iOS ecosystem.\n\nVignesh also used to be an avid CTF player and regularly participated in CTF\u2019s as a part of the bi0s team in the past.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2208,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   Good afternoon everyone and welcome to the talk.  So the title says that it is just in time compilation, but most of what we discussed  is going to be applicable for all other browsers as well.  So thanks Rana for the introduction, we can get straight away to the content.  So JavaScript, I think most of you are familiar with JavaScript.  JavaScript is an untyped and an interpreted language.  So if we have a statement that looks like let x is equal to a to b, what happens is  that it is first converted into byte code.  Byte code is a form of representation of code that is a bit lower level than the original  source code and the byte code is actually executed by the JavaScript virtual machine  which is the interpreter.  Now JavaScript code, short, this is JSC short for JavaScript code and JavaScript code is  the WebKit, is WebKit's JavaScript engine.  The byte code for JavaScript code looks something like this.  So you can see that each byte code consists of an opcode followed by a couple of, a few  operands.  So it is kind of like assembly, but it is a bit higher level.  So now let us talk about the interpreter first.  So the interpreter is the code that actually executes the JavaScript byte code.  To visualize this, you can just think of the interpreter as a huge switch case that switches  on the opcode and each case is a handler for that byte code op.  Let us just see that in action.  So typically JavaScript code is first converted into byte code.  Byte code is represented as an array, where for example the first one is add, first one  was add and the interpreter, what it will do is that it will fetch one instruction  from the byte code.  It will resolve the handler for this instruction and execute it and after that it will update  the PC to point to the next instruction in the byte code and this loop is going to go  on.  So this is basically a fetch, resolve, update.  First fetch the byte code, resolve the handler, update the PC.  However, this has a few problems.  One of the main problems is that the fetch, resolve, update cycle that this is following  is actually pretty slow performance wise, especially when we are talking about repeated  code execution.  For example like your JavaScript code has a for loop.  So each instruction is going to be fetched, resolved and updated like thousands of times.  So this makes a lot of, for a lot of performance loss.  Another issue is that JavaScript does not have types.  So the interpreter needs, so if we have a statement like this, A and B can be any type.  So the interpreter has to provide for all possible types of the statement.  Another issue is that byte code does not have any dependency between opcodes.  For example, if take this JavaScript code, we are actually, if you think, if you assume  that A and B are integers, we are actually computing A plus B three times, whereas we  could have ideally done something like that, add A plus B and store it three times.  But instead we are going to compute it three times.  So this is again leaving performance on the table.  The solution for this is to compile, compile the byte code into native assembly.  But this is only viable if that byte code is going to run multiple times.  For example, if there is a for loop in the JavaScript function, then it is viable to  compile the, compile JavaScript into assembly.  So in order to do, solve the various problems that are faced by the interpreter, we have  multiple JIT compilers implemented in browsers.  One of the first compilers, the baseline compiler, which solves the repeated for, repeated cycle  issue.  Let's see that in action.  So let's take this very simple JavaScript code, addition, multiplication, object creation.  This is first converted into byte code, and what the baseline compiler is going to do  is that, it is going to take one instruction of the byte code and convert that to assembly.  So here, just load the arguments into the registers, and call the handler function.  It does the same for the store, and it does the same for the rest of the instructions.  So this is the pseudo x86 assembly.  Now the interesting point is that in the baseline compiled code, there is no fetch.  In fact, there is no reference to the byte code area at all.  It's all assembly.  So there is no update, there is no, there is no handler resolution.  So the entire fetch result cycle is gone.  We just have assembly code, raw assembly code.  So this provides considerable speed up over base, over the interpreter.  However, the baseline compiler makes very little optimizations, very few optimizations.  We are going to see a couple of them.  So the resultant code is not the most efficient.  You don't have to read this, but this is how, this is how the JavaScript code's baseline  jetted code looks like.  You have the add instruction, and followed by the assembly for that.  One point to note here is that you don't see that call instructions that we actually saw  there.  Call handles some, you don't see that call instruction anywhere here.  That is because baseline is a bit smarter, and when I was compiling this, I used both  the operands for this add as integers.  So when I took the baseline, what it did is that it actually emitted an add instruction  directly, instead of having a call, and followed by a store.  However, it also has checks.  If either of the operands are not integers, it goes to something called a slow path, and  in the slow path, we have that call to the hand resolution function, the interpreter.  This is the generic code.  Now this is, now this optimize, this fast path, slow path thing is the, is one of the  optimizations that are, that is done by the baseline compiler.  Basically optimize the fast, optimize the common case.  That's what this is doing.  Another thing it does is inline caches, but before that we need to look at how objects  are represented in JavaScript.  Consider this object X, which has two properties and two elements.  In memory, this is actually represented as a pointer, as a combination of three pointers,  the shape, properties, and elements.  Just keep in mind that I'm just talking generically here, so each engine might have, might tweak  this a bit.  For example, Chrome might have a slightly different notation, but in essence, it remains  the same.  The shape is something that contains the property names.  You can see prop1, prop2, but it does not contain the property values.  The property values are contained in the properties pointer, and the elements are contained, 1,  2 are contained in the elements pointer.  You can see that in the shape, we have a few offset, and you might have guessed what it  is already.  Prop1 is mapped to 0, that means that if you, if I want the value that is associated with  prop1, all I have to do is look at the 0th index in the property setting, and same for  the 1.  So how do I actually access, find the, for example, there you can see 8, we are accessing  8.property.  What does the engine do, JavaScript engine do?  It first fetches the shape, then it iterates through all the properties in the shape, it  sees prop2 there, fetches the index, goes to the properties array, and goes to the required  index, which is 1, and fetches, and gets 1, 3, 3, 7, which is the value of prop2.  However, this is a little bit slow and can be optimized.  In order to optimize this, JavaScript has something called inline caching, and it attaches  a cache to that property there, property access there.  This is a cache with 3 slots.  So what happens now is that the shape is accessed, it checks the cache, but the cache is empty.  So it goes by the default way, the one we just discussed, however, after the default  way finishes, it updates the cache.  The cache is updated with the shape as well as the property offset of prop2, which is  1.  So the next time we see a shape S1, it will check the shape in the cache with the shape  of the object.  If that shape matches, if that shape matches, we have a cache hit.  So now we don't have to access the shape on top at all, we can straight away go to the  properties and access the first index.  However, what if there is a different shape?  If there is a different shape, then it's a cache miss, because S2 does not match what  is there in the inline cache, so this is a cache miss.  And if there's a cache miss, we go to the default interpreter out, and fill the slot  with the new index.  So basically this cache keeps track of all the structures that are seen at this point  along with the property offset number.  So from the problems that we discussed with the interpreter, the first one is solved by  the baseline JIT.  The second one is also kind of solved with baseline JIT's fast path slow path approach  as well as, as well as the inline caching approach.  However, the third part is never solved, there's still no, the baseline JIT still has no dependence  between objects.  For this, we have something called optimizing compilers.  Optimizing compilers are slow to generate code.  Optimizing compilers do not work with the bytecode because bytecode is not optimal here.  So optimizing compilers always have their own representation of code.  However, the code that optimizing compilers emit is very much more, much much more faster  than any of the other ones.  Slower the optimizations, more efficient is the code, but slower is the compilation.  So typically to offset for the slow compilation, what browsers do is that they have multiple  compilers, not a single compiler, multiple compilers.  Each compiler doing more optimizations than the previous one.  Also this, for compiling code, you need types and JavaScript is an untyped language.  So all the, all the optimizing compilers are going to speculate on types, just like  the baseline compiler did.  So pictorially, the previous slide represent is, it looks like this.  Source code is now parsed into the, by the parser into the bytecode.  Bytecode is consumed by the interpreter.  The interpreter executes the bytecode and the baseline also executes the bytecode there.  And the profiled bytecode is now parsed to the JIT compiler, which emits an optimized  code.  And if there is a speculation failure, it goes back to the interpreter or the baseline  compiler.  Now let's shift gears to focus more on JavaScript core and less on the other browsers.  JavaScript core has four tiers of execution.  We already saw the LLN, which is the base, which is the interpreter.  Then we also saw the baseline JIT.  However, the other two, DFG and FTL are optimizing compilers.  So the FTL is the fastest, emits the fastest code, but it also takes the longest to compile.  If there is a speculation failure in DFG or FTL, control flow shifts back into baseline.  So you can think that, you can see all this complexity there and more the complexity,  more the chances of bugs.  I was saying that interpreter always works with bytecode.  We also saw that baseline also works with bytecode.  However, DFG works with a different representation of code called DFG IR and the FTL works with  three IRs.  It works with the DFG IR of course, but it also has two unique IRs of its own called  D3 and DIR.  Now let's talk about typing in DFG.  In DFG, types of a, JavaScript has variables and types of a variables in DFG is represented  using two things, speculated type and abstract value.  Now speculated, both of them represent the type of a variable in JavaScript.  Now speculated type actually signifies the most possible value of the type.  For example, if I have a JavaScript variable that has the speculated type int, it basically  means that most probably this variable is going to be an int, but it can also be anything  else.  However, if an abstract value says that the JavaScript variable has type int, it is going  to be int.  It can be nothing else.  This means that speculated type needs to be checked at run time because it's for all purposes  it's just a guess.  Educated guess for just a guess, so it has to be checked at run time.  The abstract value is a compile time pro, compiler proves it at the compile time, so  it never needs to be verified.  It is trusted by the compiler.  Speculated type is calculated using profiling data, whereas abstract types are calculated  using something called DFG AI.  AI stands for abstract interpreter not artificial intelligence, and speculated type is used  to construct RIR, whereas abstract values used to optimize RIR.  They have their own functions and they don't conflict with each other.  Now let's look at how abstract values are actually represented in memory.  So if you look at the source code for JavaScript code, everything is in C++.  This is the structure that actually has the abstract value, that actually defines that  abstract value.  So it has a field called mstructure, which has a list of all possible shapes an object  can have.  In JavaScript code that shape thing that we saw earlier is also called a structure.  We are going to use that interchangeably.  Structure means shape, shape means structure.  So this mstructure is a list of all possible structures a variable can have, and mtype  is a list of all possible types this variable can have, kind of conflicting right?  So let's do this with an example.  Let's say a variable has mstructure as let's say S1, structure S1 and a type int.  What this means is that this variable can either be an integer or an object with type  S1.  It can be nothing else, integer or an object with type S1.  We are going to skip the next two objects for the purpose of this presentation.  Finally we have the mvalue, mvalue field what it signifies is that it holds the address  of an object if an object is const.  Let's do that with an example.  Take this JavaScript statement for example.  This is, this has the const specifier added to it.  What this means, what this const tells is that this object can never be modified.  So if you try to do object equal to 5 later, that's a JavaScript error.  So that means the abstract value of this object will have the mvalue field as the address  of this object because it's never going to change.  So the mvalue is the address of the object.  It's important to note that mvalue and structure do not conflict with each other.  Mainly because I can modify the value of the object however the structure, so that the  structure changes.  However the address of object is still constant.  So mvalue and mstructure do not conflict with each other.  There are two special type, special values that each of those fields can hold.  One is called the top which is, which stands for anything and one is called the bottom  which stands for nothing, another thing.  So which, this means that if mstructure is top, this means that this variable can be  any type, any type.  It's an object but it can have any type.  So if the variable is, if the mstructure is bottom, then it basically signifies that this  variable can be, it will have no shape at all.  That means it's a primitive value, integer, flow, whatever.  The abstract interpreter is used to find the concrete type of the node.  It has all, it also has other implications.  For example, it's used for constant folding but, constant propagation but we are not going  to discuss that here.  The other thing is that if you are reading the source code, it's always called DFG-AI  or AI in the source code.  AI stands for abstract interpretation.  Now we're going to look at a bug in the abstract interpreter itself but to do that  we have to be more familiar with property accesses in DFG.  You are probably familiar with this now.  We are accessing a property P1 on that object.  Whenever interpreter sees something like this, it attaches an inline cache, IC.  And the IC right now is populated with S1, 0.  Shape S1, offset 0.  So when DFG tries to optimize this, it splits it into two, sorry, it splits it into two  opcodes.  One is the check structure and one is the get by offset.  The check structure checks the structure of the object, this object, with S1.  Where did it get S1 from?  It got it from the cache.  And the get by offset fetches the actual property from offset 0.  Where did it get the 0 from?  From the cache.  So DFG basically bakes the inline cache into the IR.  An interesting point to note about check structure is that if that comparison fails, this is  basically a comparison, compare, check if object structure is same as S1.  If that comparison fails, this is a speculation failure and no further code is executed.  So, now let us look at an example.  Just take a moment to read this JavaScript code.  It is just creating three objects, X1, X2, X3.  X1 has the shape S1, where P1 is at offset 0.  This one has shape S2, P1 is at offset 0 again, even though shape is different.  Offset is same.  This one is X3.  Shape again is different, but offset is again the, in this case the offset is also different.  P1 has the offset 1.  The other two had an offset of 0.  And a point to note is that we are going to be studying the property access arg.p1.  Now we know that arg.p1 is going to have, arg.p1 is going to have an inline cache.  The data in that inline cache is represented in JavaScript code using a class called GetByStatus.  So, this is again a class and this is used to track the property access.  GetByStatus is used to track the property access of that issue, of that property access.  And now we can forget about all the other fields.  The only field that we care about is this vector.  This is a vector of GetByVariant.  So, now we have to go into GetByVariant and we have to disassemble it.  It's a complicated structure.  You do not have to read any of that.  What you have to note is that the GetByVariant is something that keeps track of structures  with similar property offsets.  Again, we will see this with an example rather than this thing.  So, let's bring that example which we saw earlier.  X1 and X2 have a shape S1 and S2.  And the point to note is that both have P1 at offset 0 even though their shape is different.  So, this means that V1 is a variant.  So, GetByIdVariant with, that holds S1 and S2.  And V2 is a variant that holds S3.  The point here is that if your offset is same, you have a single variant.  If your offset differs, you have a new variant.  So, S1 and S2 have the same offset, offset 0.  So, they are both clumped together in a single variant.  Whereas, S3 has a different variant.  So, it has, S3 has a different offset.  So, it has a different variant.  The GetByStatus is a vector of all these variants.  Now, what we are going to do is, we are trying to ask how do we create this GetByStatus using.  To create a GetBy, to create all these variants, statuses and all, what we need is that at  this point, arg.p1, we need to know what is the structures that arg can have.  What are the structures that arg can have?  One way to find that out is the inline cache.  The inline cache associated with that arg.p1 access will hold all the structures that it  has ever seen.  But, another way that we can compute that is using what we just discussed are abstract  values.  Because abstract values also, abstract values also signifies more or less the same thing.  Speaking of abstract values, let us actually look at some buggy C++ code.  So, this is the code for abstract interpretation of GetById.  What is GetById?  Let us say we have an object.p1 access.  Then, object, then if we have an object.p1 access, then the GetById is an opcode that  is, I mean, is the DFG opcode that signifies that property access.  So, first we fetch the abstract value of object.  Then, we fetch the p1 as a string.  It is string implementation p1.  We fetch that.  We compute the GetByStatus that we just discussed using the abstract value.  We already discussed that one GetByStatus has multiple variants and each variant now  has to be, the for loop has to traverse over each of the variants.  Now, this is a complicated bug.  I am trying to simplify it as much as possible, but still it is a complicated bug.  So, now each variant as it is traversing, it is calling this inferred value for property.  What this whole code is trying to do is to predict the abstract value of the result,  object.p1.  We know the abstract value of object.  What is the abstract value of object.p1?  This whole code is essentially trying to find that out.  So, that is found by this property, inferred value for property.  Now, what this function does is that it checks if object is a constant, conspecifier for  example.  And if it is a constant, then it goes directly and fetches the option that it has passed  and fetches that value.  So, it knows the type of object.p.  And it does that for all the variants and the results are merged together.  However, this has a problem here.  We are actually doing, in the previous couple of slides, we are actually doing, making an  array access on the property offset in this code.  But we are, but the offset is keeping on changing in the for loop.  Initially it will be 0, then it will be 1, offset comes from the for loop.  And that should not happen because we are trying to access object.p1, which p1 is at  offset 0.  But this code is trying to access offset at 1.  So, this will essentially lead to an out of bounds error.  It will lead to all kinds of error.  Long story short, this code makes no sense here.  No sense.  So, this is actually going to give incorrect results of the resulting abstract value.  Because we can see that with an example again.  Let us say we have an object, let us say we have an object obj1 with two properties s1,  two properties p1 and p2.  Then both of the properties here are actually this pointing to the same value.  And we have an access object here, property access.  We are going, trying to exploit all property accesses.  So, let us say that somehow, we do not know how, but somehow that property access has  the abstract value that is shown here.  Two structures s1, s2 and a value, and a const value of obj1.  So, this value is effectively obj1 and the offsets are going to be 0 and 1.  So, what is going to happen here is that, first we try to get the property at offset  0, which is, this is going to be p1, it is correct.  In the next iteration of the for loop, this is going to be 1.  This is an out of, this will, might or might not.  In this case, at offset 1 we have p2.  And we are trying to compile an access to p1, but the compiler is reading other property  p2.  The compiler itself is confused at this point.  So, it reads some incorrect value, the resulting abstract value is also incorrect now.  So, just to take a moment, abstract value is something that is trusted by the compiler,  but due to a bug, as abstract value is now wrong.  So, a trusted internal value is now wrongly computed.  This means that we have avenues for type confusions everywhere here, from here.  So, one of the main places to look for type, where abstract values are used is constant  folding, because it is a constant folding case.  So, what is constant folding?  Constant folding is basically an optimization case in the DFG IR.  And let us see what it does for the check structure opcode.  To recap, when we have a property access like this, DFG converts it into two access.  One is a check structure, one is a get by offset.  Get by offset is basically fetching the property value, whereas the structure check is done  by the check structure.  And what this code is going to do here is that, it first fetches the abstract value  of object.  What does the abstract value of object contain?  It contains all possible structures object can have.  And then it fetches S1 from here.  This set is basically S1.  Now, if the, now the compiler asks the abstract value.  What are the set of structures that, structures that this can have?  What are the set of structures that object can have?  And if all, if the abstract value reports to the compiler that object can only have  one structure, S1, then this entire check structure, entire check structure can actually  be eliminated here.  Which we, and now coming back to our code.  Our bug was that we have an incorrect abstract value for this.  And if we access a property on that, on that value, then check structure, this is, a property  access is actually split into two DFT opcodes.  The check structure is incorrectly eliminated because the abstract value is incorrect, the  check structure is incorrectly eliminated.  Because check structure is, elimination is based on the abstract value which is now incorrect.  So we have an incorrect elimination.  So we just have a get by offset which is a direct pointer access without any checks.  In reality, what happens is that the compiler thinks access object can only have the structure  S1.  However, in reality it can also have the structure S2.  So which means that if it has the structure S2, which we, I did not even show S2 here.  It is just some random structure S2.  Then object.p1 can be a random access, can be a random number.  It can be 1, 2, 3, 4.  For all I know, access can be 1, 2, 3, 4.  And this one is now trying to access, do a pointer dereference on 1, 2, 3, 4.  Which is, which is why.  So if I run that in GDB, this is how it looks like.  I crash with rcx as 1, 2, 3, 4.  Because this crashed the entire engine by doing an arbitrary pointer dereference.  So I am from here writing an exploit is actually simple from here.  So we are not going to talk about writing an exploit, but it is pretty simple.  And this bug was patched in, I think November last year.  It was introduced in 2014.  This is a bug, this is a bug so complex that it lived in the compiler for 8 years.  So 8 years Safari was vulnerable to this.  Safari could have been exploited using this bug.  Only in November it was patched.  So that is the advantages of complex bugs.  Now let us look at a simpler bug, much more simpler bug.  For this we need to know what is a JS value.  We know, we know that if object is equal to,  if we have JavaScript statement like this,  internally JavaScript statements, JavaScript core actually stores obj as a pointer.  Pointer means all upper 15 bits are null.  Because that is how virtual memory works.  Virtual memory only uses the lower 48 bits.  So upper 16 bits are actually null.  If you are storing a number,  JavaScript core actually uses this FFFE.  So upper 15 bits are set.  And finally if we have a float, float is imported using the IEEE 754 format.  This is the 1.1 IEEE 754 will give us some value.  And JavaScript core what it will do in turn is that  it will add 2 to the power 49 to our IEEE imported thing.  Now if you have done bug hunting before,  every addition is suspicious to,  every addition is suspect to integer overflows.  This means that if the upper bits of an IEEE 754 are all set,  then this can overflow.  So the compiler has to protect against it.  In theory it can overflow, in practical it will,  in practice it will never overflow.  This is because the IEEE 754 format says that  if the upper bits are all set, it is not a number.  This is not a number.  JavaScript only honors one not a number value and that is this one.  Everything else it does not honor.  So now let us go back into the code base.  This is the code that converts JavaScript IR,  DFG IR into assembly.  So this is the code that has been compiled.  We have an array access and that array access is  being compiled to assembly.  However this is not a simple array access,  it is a floating point array access.  Speciality of float 64 arrays here is that  float 64 arrays hold raw floats, IEEE floats, not JS value.  And another interesting point is that  they are completely user controlled.  We control every single bit.  So this means that when we do a get by val,  this means that when we compile it,  the compiler should actually check,  the compiler should actually check,  first convert the float into,  convert the float into a JS value  and also check each of the bits.  The compiler does check,  convert the float into a JS value,  but it never checks whether the top bits are set or not.  So this means that we have an overflow here,  which should never have happened.  And we again have an arbitrary pointer dereference.  We actually did a,  me and my colleague did a full talk on this.  I assume you can watch this there.  To conclude,  some takeaways here are  to hunt for assumptions in code  and to compare implementations between various compilers.  Another idea is to look for variants.  This is that get by, that nan value patch,  that was patched.  It was patched two times,  three times, four times, five times.  It was patched.  This work has been there in the compiler since 2022.  Every time in different parts.  It's interesting to look at all the variants  and it's also interesting to look at the depth.  The abstract value is so deep  that it's lived in the compiler for eight years.  So finally, as a demo,  this is the nan exploit running on an iPhone.  And it's iOS 15  and it's actually reading the slash etc slash password.  So that's more or less it.  I'm running out of time.  I'm sorry for overrunning it by a few minutes.  And I'll be around if anyone has doubts or questions,  then I'll be around the place.  Thank you, Ignis.  We can open the floor for a couple of questions very quickly.  If anyone's got any questions,  you can use them now.  Yeah.  With such a complex code base like JavaScript core,  how do you find the ability to track virtual methods  being called in vtables deep and deep into the code base?  Do you usually use that dump disassembly  or dump bytecode thing?  Yeah.  So typically what people do is that you read the source code.  But rather than reading the source code,  I feel like reading the IR  and that dump disassembly is more helpful  than reading the go and reading the source code.  So I would say, yeah,  read the IR and then read the source code.  Thank you so much for your talk.  I was just curious how these two bugs were found.  Was it through auditing or fuzzing or things?  So the first bug was not mine.  The abstract value bug is just a bug  that I thought was so very interesting.  The second bug is mine.  It was found by me and my colleague.  So it was found partially by fuzzing,  partially by auditing  because we were auditing a code  where a fuzzer actually found the crash.  The fuzzer crash was not exploitable,  but when we audited that code,  we found a different bug.  So we found this by looking at just reading code  and yeah, mainly by source code auditing.  Any more questions?  All right.  For any other questions,  you can take your seat with Vignesh.  Thank you very much, Vignesh.  Thank you.


url: https://www.youtube.com/watch?v=foOyhOUreno
title: Off-By-One 2024 Day 1- Uncharted Depths Navigating Overlooked Vulnerabilities...
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=foOyhOUreno",
    "title": "Off-By-One 2024 Day 1- Uncharted Depths Navigating Overlooked Vulnerabilities...",
    "description": "Uncharted Depths Navigating Overlooked Vulnerabilities in the Sea of Million WordPress Sites\n\nAbstract\n\nContent Management System (CMS) platform is still one of the best options to build a website quickly. CMS provides a user-friendly interface that allows non-technical users to easily create, edit, and publish content without requiring extensive HTML, CSS, or Javascript programming language knowledge.\n\nWordPress is still the most popular CMS platform, powering 43.2% of the websites online, with a CMS market share of 63.5%. With its popularity, it\u2019s prone to massive exploit attempts. The WordPress Core itself is not the actual target, the plugins and themes are the actual target of an attacker with the vast majority of the security bugs being found in plugins and themes.\n\nThis talk will cover deep technical details of overlooked impactful vulnerabilities discovered in WordPress Core and across the most popular WordPress plugins, with each component having more than a hundred thousand active installations.\n\nWe will also cover vulnerability in one of the most popular libraries used in plugins and themes, which could affect more than 7 million websites.\n\nWe will use multiple cases of overlooked XSS and privilege escalation attack vectors which could be easily exploited in the wild. We will show how we found these vulnerability cases and how to secure the code from these potential vulnerabilities.\n\nJoin us for the journey of exploiting the WordPress ecosystem (An Exploit demo is included too !)\n\nSpeaker\nRafie Muhammad is a security researcher at Patchstack. He specializes in web application security, WordPress security and PHP code review.\n\nRafie is passionate about web application security with a white-box approach. He likes listening to podcasts while reading a bunch of PHP code on VSCode.\n\nWith almost 2 years experience on WordPress security, Rafie has secured critical and most popular WordPress environments ranging from WordPress Core, Plugins and Themes.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2915,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   So, hello everybody. Here we are going to present a title named Cardcaptor Devs, the Navigational Product for an Ambitious and Seamless Optimization of Wordpress Sites.  So, for starter, let me introduce myself. My name is Rafi Muhammad from Indonesia.  Currently, I am a CWP Researcher at PatchTech, also known in the internet with the username of erisd.  I am mostly focused on the web application security. I am also a part-time executive player for the SKSE team from Indonesia.  I am also a bug bounty hunter and of course, a PhD advisor.  So, for the intro, in the first place, why target CMS from the security research perspective?  So, CMS platform itself is still the first go-to solution for managing content on websites without the need for technical knowledge.  So, basically CMS is mostly used by non-technical person to create a great website.  In 2022, over 67% of websites will utilize CMS.  Also, most of the times, CMS has a lot of features for us to check for vulnerabilities.  For that, why are we targeting Wordpress?  First of all, Wordpress covers around 43% of all websites.  And also, it has around 34% websites are in the top 1 billion websites.  Also, Wordpress has the CMS market share of 63% in 2024.  It is much higher than any other CMS platform like Joomla, DeepPul, and Edge.  It's also an open source.  It's pretty easy to familiarize if you are a beginner to security research.  And of course, it's in the PhD.  So, we will get to know Wordpress itself.  So, Wordpress has three different components.  The first component is the form, which is the CMS platform itself.  The second one is the plugin, which is an additional piece of software that can be installed on Wordpress website.  It extends the functionality and has new features.  We also have the theme.  It is similar to the plugin, but the main purpose of it is for the visual appearance of the website.  So, when doing our research, we are mostly finding vulnerabilities in the plugin itself,  because the theme mostly doesn't have a lot of features in it.  For some cases, there might be a premium theme, not a free theme,  that has an all-in-one solution.  So, basically, in that kind of theme, you have a lot of features to check.  So, we will get to know the Wordpress free repository itself.  So, the Wordpress free repository itself has about 60K clients.  It ranges from 10 active installations to 5.  It also has 12K themes, hosted in the free repository.  So, there is a lot of plugins and themes for us that can be used for research purposes.  So, we are moving on to the scanning Wordpress port base.  So, Wordpress port plugins and themes has a CPM, or track register.  If we got a Word or Regex pattern to search for a potential affected plugins or themes,  let's say we want to search for this Regex in any plugins or themes in the free repository,  there is a tool called wp-directory.net.  It's an example of a few of the websites.  Or also, if you want to deploy it yourself,  they have also the GitHub repository for us to manually deploy the tools inside of our server.  So, we move on to the research target.  So, in order to do a proper research in the Wordpress environment,  we have to make the right decision on what plugins or themes that we will be researching.  So, there is a graph.  If the plugins or themes have a lot of popularity or has a huge active installments,  the likelihood of critical or impactful vulnerability found or exist is really minimal.  That's because a huge active installation of plugins or themes,  mainly are already taken off because it's also open source.  And actually, the port quality itself is generally much better than the low install of plugins.  So, you have to choose here if you want to try to find a vulnerability in a high installation of plugins or themes.  And you probably will not get a nice finding.  But, if you want to try research on a low install of plugins,  like 10k or 50k installation count, you might get a decent finding on the plugins itself.  So, my initial approach for doing research in the Wordpress environment.  So, for the free version, we can fetch the plugins or themes via the installer, via the Wordpress core itself.  For premium version, we can try to fetch the null version.  The null version itself is just simply like the cracked version of the premium plugins or themes.  So, there is a lot of websites that hosted null version of the plugins or themes.  One of the example is the wayadone.com website and also the wplocker.net.  Disclaimer for the null version, because it could be dangerous on the test.  Because in some cases, we do find a backdoor code in the null version of the plugins or themes.  Also, after that, I usually analyze the code.  Additionally, using the dynamic analysis, such as xvbuffers.  So, choosing priority for tools in Wordpress environment.  So, basically I have a list of tools that I will type to find when I first try to research or apply the plugin.  So, the first tool that I will look for is the prefetch escalation.  The second one is XSS.  Why XSS is the second priority for tools?  Because in Wordpress, basically because of the behavior of Wordpress, if you find a single XSS in Wordpress,  you can basically escalate your prefetch to any role in Wordpress.  Because you can just simply register a new user when you start a role.  The third one is SPL injection.  And then the fourth, because it's PHP-based, we also look for PHP object injection or its initialization.  The next one is RCE, of course.  So, we have to look for LFI, because it's PHP.  And then the last one that I try to look for is arbitrary file rate and duration.  So, we move on to the case studies.  First, we will take a look of the overlooked XSS case studies in Wordpress.  So, the first example is one of the CPE that I found.  It's a site-wide prefetched XSS in a free news library.  So, some details about the vulnerability that it is introduced in version 1.0.8.  And it is patched on version 2.5.10.  The vulnerable code page itself is around 8 years and 1 month.  So, this library is massively used in Wordpress plugins and themes.  It is approximately installed in 1,300 free plugins and a couple of themes in the Wordpress repository.  So, by combining the active installation of the plugins and themes,  the installation of the free news library is around 7 billion.  So, the background story of this finding is,  initially I am looking for foams on TablePress plugins which is used in this library.  Notice that it is a free news library.  And because I didn't find any interesting vulnerability in the TablePress itself,  I decided to find a vulnerability in the library itself.  And it turns out that it is a vulnerability to XSS.  So, we jump into a little bit of the code review.  Here we can see in the right side of the slides,  there will be a call to the add sticky function.  So, in Wordpress, there is a feature called admin notice,  which is a feature for the developer to create a pop-up message in the admin area.  So, basically in Wordpress, the admin area itself will be using an endpoint of WP-Test-Admin.  So, basically the add sticky function will create a message to the admin area.  In this case, we can see that it uses the fsRequestGet function with the word test plan parameter,  and also below it is using the word test email parameter.  So, the fsRequestGet function itself is just like a simple function wrapper to fetch a request global variable in PHP.  So, the add sticky just simply will call the add function,  and then the add function will process the message to the message object,  and the message object will be stored in the __admin__message object.  Then, this admin message object actually will be called when the application tries to call the admin notice function.  So, we can see that it will try to do an iteration on the __admin__message variable,  and then it will call the __admin__notice.php function,  which in the right side of the slides, it will just simply echo the message via the false variable.  So, because the fsRequestGet function itself just simply achieves or receives the request global variable from the user,  and there is no escape or sanitation on the data, we can basically achieve access on these cases.  So, what about the fetch from the vendor?  So, the fetch from the vendor is they are adding an additional function named fsSanitizeInput,  which will be used inside the fsRequestGet function.  So, basically the fsSanitizeInput function will sanitize the input using the sanitizeTextField function.  The sanitizeTextField function itself is basically just a function to strip any of the HTML type or HTML string on the input.  So, we move on to the example exploit.  So, in this one, we have two cases for exploit.  The first one is the opt-in cases, and the second one is the skip opt-in cases.  So, when you try to install a plugin in WordPress, sometimes the plugins allow the users to opt-in for newsletter message or promotion message and any kind of message.  So, basically we can pop the replicant accesses based on the user's option if he is opt-in or skip the opt-in.  So, for this example, we will try to demonstrate with the opt-in example.  So, we are using the TableauPress plugin as an example.  We are using the vulnerable version.  And then, the admin tries to click the opt-in.  So, it's opt-in to get email notification for security and filter updates and so on.  So, admin is just alone in the plugin and accept the opt-in.  He then checks his email for the confirmation link for the opt-in message.  And then, after getting the link, he just simply can visit the opt-in confirmation link.  After visiting the opt-in confirmation link, we can just simply put the example of HSS payload using the admin account to test for the HSS.  In this case, we put the HSS on the WordPress plugin.  So, the HSS is triggered using the purchase email.  So, basically the HSS can also be triggered on any WP admin.  So, in this case, we test it on the options.general.php file.  So, basically this replicant HSS can be triggered on any WP admin or admin account.  That's why we call it like a side-wipe.  Next case study is the side-wipe unauthorized source HSS in MySQL cache.  So, the vulnerability details is introduced in version 5.  It's in version 5.7.0.1.  The vulnerable code page is around 1.3 months.  It has 5.7.0.1.  So, the background story of this vulnerability is I initially looking for a broken access control API.  And it turns out I do find a broken access control API, but it also produces an unauthorized source HSS in MySQL.  So, as you can see in the example of what we view, there is a register as root function,  which will register a custom API endpoint using the cdnstatus endpoint.  It will check the permission using the isfromfault function.  As you can see, the isfromfault function just returns true.  So, basically any unauthenticated user can visit this endpoint.  So, the callback parameter is set to the cdnstatus function.  If we see the cdnstatus function, it will basically call the update cdnstatus function.  The function itself also just calling another function, which is the process cdnstatus, with our supplied postfirm method of result.  In the process cdnstatus function also, it will call the admin display succeed function with our supplied method, which is the result variable.  So, basically the succeed function itself will forward the message, the msg variable to the add notice.  So, it is the same scenario as the previous.  The vulnerability resides in the add notice feature.  So, it will add the notice with the message, and then it will build the notice using the build underscore notice function.  And it will basically return the html string with the message or in this case, on the askdl variable directly to the html.  So, the patch from the vendor is, they basically first try to fix the vulnerability control by applying some kind of hash tag in the function itself.  It is an md5 tag of a secret pocket.  And then they also apply an shtml function to escape the input from the user.  So, the example POC for this is a simple pull request.  You can specify the address payload inside of the result, the main service parameter.  Or you can also specify in the result, underscore message variable.  So, we will test this example POC.  POC.  So, in this case, as a result, an admin account.  Then, as a non-dedicated user, we just perform this pull request containing the SS payload, the cdn status, and the NPA.  After executing the pull request, admin can request any page on the HW admin, and it will trigger in the HW admin area.  You can also test with a different variable, which is the underscore msv parameter.  And it will also trigger the XSS in the HW admin area.  Okay, we are moving on to the last cases for the XSS.  So, yeah, for the XSS, we have fun stuff like this.  So, the details of this case is introduced in version 6.1.0.  Next, in version 6.1.6.  The front of the port page itself is one month, which is quite short compared to the other vulnerabilities.  It has active installation of 2.0.  This vulnerability is also unique because it involves a vulnerable WordPress core function.  So, this vulnerability can only be exploited in WordPress core function prior to version 6.1.2.  So, the background story of this vulnerability is initially I'm looking for XSS on the custom shell implementation of the trans-customer-first file itself.  But, yeah, I found a different case of testing and write the function.  Yeah, so if we try to look at the source code here,  we can see in the left side there is the current screen function, which will set this view variable to get a status parameter.  So, it will use a scientist.txt fill function.  As you are aware from the previous example, the scientist.txt fill function will try to strip any HTML tags from the input.  But, it will not strip or escape the string like double quotes or single quotes.  So, in this case, if we file sanitization using this function, we can still receive XSS if the string is placed inside of single quotes on the HTML attributes.  So, we have an admin body class function, which is an action from the WordPress core itself.  The function itself will append our previously stated this view variable to the classes and will receive the return in classes from the function.  So, if we look closely into the WordPress core itself, that is located in the wp-admins.php,  we can see that the WordPress core will fetch the value from the admin body class action or filter to the admin body class variable.  And then, it will simply echo the admin body class variable to the HTML string in the body type HTML.  So, there is no proper sanitization done in this case.  So, we can simply put our domain name as XSS.  So, for the patch from the plugin side, they decided to use a function named as underscore.html function.  This function is different from the Cytus.txt function because the purpose itself is actually to escape strings inside of HTML.  So, it will escape single quotes and double quotes in the string.  So, it is safe to use this function for these cases.  Also, from the WordPress core side, the core security team also decided to use as underscore.html function to the admin body class variable.  So, you can see the example payload for this.  So, it is different from the other two XSS cases.  In these cases, we can only trigger this XSS on a specific envoy.  It is the wp-admin-edit.jsp with the post type set to SACF, underscore, underscore.  So, we can set our XSS payload in the post status here parameter.  In these cases, because it is in the body type HTML, we can use the convert all to test for the XSS.  So, as an admin, we can simply visit this envoy and trigger the XSS.  Oh yeah, it is not the last one yet.  The last one for the XSS cases is the WordPress core dedicated XSS.  So, in the WordPress core itself, we have several roles for users.  In this case, we will demonstrate the XSS on the contributor role on the WordPress core.  So, it is introduced in version 5.9 and it is fixed in version 6.5.5.  The available content is around 2.5 months.  Active installation is mainly used in selecting any active WordPress core instance.  The background story.  Actually, this patch is only 2 days ago, on Monday.  Initially, I am searching for any tools on the register to debug the process.  So, as you can see in the left side of the slides, we have a render block or template part.  So, in WordPress, we have a feature called block, which is just a piece of code that can be used from the visual editor side to display some documentation.  So, in this case, the further block is the template part function.  So, it will retrieve attributes parameter.  So, in this case, the referable attribute is the attribute's top name function.  It will be constructed to the HTML underscore tag variable.  We will use the S underscore IDL function.  But it is not enough to prevent XSS because the HTML underscore tag function itself will be appended directly to the opening tag and closing tag of the HTML.  So, we can just simply put a script and space src to our .js file and we can execute XSS.  The patch for this vulnerability is the core security theme 2 days ago.  Just implemented a check whitelist tag using wp-ks-es-lower-html.  So, this is basically just a limited set of lower HTML tag.  This consists of tags like div.  So, we cannot input any other tags such as script.  So, for the vulnerable block, we can just call the template part block in the content.  And we specify the tag name attributes to our development script src and our XSS file.  So, in this case, we are using a contributor role user.  Then, we will try to draft a post.  Then, we copy the XSS file on the block itself to the content parameter in the host request.  We then try to host like an example of .js file in our host.  We just test contributor.nr.  After setting up the src parameter, we can test the XSS by simply view the preview of the post.  So, in this case, because it is only performed by a contributor role user,  the main target for this kind of XSS is basically for the administrator to deliver the XSS.  So, basically contributor role cannot publish a post or a page.  It can only make a draft and it will need to be accepted by the previous user.  So, we move on to another vulnerable type of developer, vulnerability.  Now, we are going to discuss about the preferences condition case studies.  So, the first one is an unallocated account type of work in SNCL X.1.4 Elementor plugin.  Some of the details are introduced in version 5.4.0.  It is patched in version 5.7.0.1 and the kernel reportage is around 7.9.  It has active installation of the plugin recently.  So, the background story of this plugin is, I am initially searching for bones on the  custom registration process of the plugin, because the plugin has many features on it.  But, it turns out the contact over itself is found in another feature of the plugin.  So, the plugin has a login or register function, user function,  and then it handles a couple of actions on it, like login and register.  And, send password reset and also to reset the user password.  So, one of the functions that is vulnerable is the reset underscore password function.  So, you can see in this example is the rp underscore login variable will be set to our  supplied postmark parameter of rp login.  So, in this case, the code will try to pass the user object using the getUserVariable function,  using the rp underscore login variable.  So, the login in this case is just like the username or email from the user.  So, it then will check if the user exists and then it will try to perform a reset underscore  password function on this object with the supplied postmark parameter of the user.  So, basically with this case, because there is no check of password reset key,  we can basically change the password of any users in the website.  So, the patch for this vulnerability is simply by using the checkPasswordResetKey function,  which will check a unique password key from the database.  So, basically we will receive this key on our email when we are trying to reset our password.  So, the POC demo is quite simple for this one.  First, we try to login as admin with our password and it cannot because the database has a wrong password.  And then, we try to execute the script with targetUserAdmin and the password is 123.  So, if the password is changed, users will be logged out from WordPress.  So, admin cannot log in to their phone.  And we can just simply log in to the admin account to see if our password is changed.  So, the next one is how to get WordPress explanation in an HTML5.  So, in this case, the vulnerable webpage is a round format.  It also has a history collection of 100 pages.  So, the background story of this is, I am initially searching for things in the WordPress explanation process.  And it turns out, this is one of the tools for WordPress explanation.  So, it is very simple.  Because the function itself has a custom function to register the user.  It is the html.address.register function.  So, basically, the function itself will try to construct a user underscore data variable.  As you can see, the variable also accepts a role field to it.  It is directly supplied by the user using the post parameter of write underscore role.  And then, it will check the data using the html validation data.  And then, it will try to register a new user using the wp underscore user underscore user function.  So, the html validation data itself only checks the src validity of the data.  It is like checking the length and then checking the set of characters.  So, it is not checking if the user supplied an arbitrary role on the request itself.  So, the best is very simple.  Just by removing the role field from the user data variable.  So, the user can only be registered to the default role set by the user.  We put the POC demo for this one.  It is also quite simple.  First, we check from that new panel.  We check that there are only two users.  And then, we try to execute the script with user name and password set to 123 with administrator role.  So, after we execute this script, we are creating a user with administrator role.  So, we can see that there is a new user with administrator role.  And we can just simply log in to the account.  And we get the administrator role.  Yeah, I think this is the last case of the previous explanation on this presentation.  It is an unauthorized account that is offered in Jupyter Xcode plugin.  So, it is quite different from the other example because it is a premium plugin.  Since it is a premium plugin, we cannot test the version of it.  But it is patched in version 3.1.2.  It is also an unauthorized account.  So, the background story of it.  Initially, I am just a programmer.  So, we ask for the registration process.  But the content of it is not in the registration process itself, but in the social role of the user.  So, as you can see in the left side of the slides, we have the ISS handler function.  It is a part of the mem variable.  And the re-identifier variable directly for user input was parameter.  And then it will try to construct a user ID variable using the email access function with the email parameter that we supplied previously.  So, it will basically just check if the user is accessed from the supplied email.  After that, it will call the setUserFacebookID function using the user ID variable and the FBID variable.  So, the setUserFacebookID function will set the user metadata of the target user, which is the user ID.  So, the password metadata that will be set is the social media user FBID metadata with the FBID value.  So, basically with this, because there is no check in place, we can basically set any user's social media user FBID metadata to any string.  Why is this important?  Because there is also another function, which is called FacebookLogInsertion, which will fetch a value variable from the get parameter.  And then it will try to search a user using the getUser function.  And it will search for a user that has a specific value of social media user FBID.  And then it will construct an ID variable from the user object.  And it will simply set the current user and the authentication key of the request to the targeted user ID.  So, in these cases, we can just log the ID to any of the users by only logging the email.  So, for the fetch for this vulnerability, because the documentation is wrong on the social media feature,  the vendor decided to apply a proper fetch by checking the access token of the user itself.  So, now the users need to supply, in this case, it's a Facebook social login.  So, the users need to supply this Facebook access token.  And then the application will directly retrieve the email and the FBID directly from the Facebook Ramp API endpoint.  So, for now, users cannot accept any of the user's metadata anymore.  As you can see in the next page, the user ID is now constructed from the API email which comes directly from the Facebook endpoint.  So, we can try the new POC for these cases.  We can now log in as an admin, as an example.  And then, as an example, we can use any email on the admin account.  For these cases, we will use admin.admin.code email.  And then, as an authenticated user, we can just simply execute this script using the targeted admin email,  the social login path, and then any string that we want to set the FBID to.  In this case, we set the FBID to 1337.  So, after executing the script, we get the link to log in as a targeted user.  In this case, it's admin.startup.com.  So, as an authenticated user, we can just simply visit the link from the script.  And then, after visiting the link, we can simply log in as an admin.startup.com user.  So, we have come to the end of the presentation.  So, the conclusion is, first, WordPress is pretty much still a rare find from a security research perspective,  especially from the open source security research.  Most of the critical and impactful bugs found are rather just a simple, but overlooked bug.  There is also still a lack of details and attention to common use action and process in WordPress plugins or themes.  More research needs to be done on the most popular components in the WordPress ecosystem.  Also, there is a lot more potential research on the Southwest China tech, like the previous example,  specifically towards the library and the South plugin core.  So, yeah, any questions?  Thank you.  Thank you for a nice, great speech.  I have two questions.  The first question is that, when you read the code for finding vulnerability,  do you find the code that occurs vulnerability directly?  Or do you take a reverse track to the surface or surface from the core?  And the second question is that, while you take this research on,  did you find yourself any kind of standard to choose, probably,  if you establish your own WordPress blog?  In the security perspective, I mean, how to find a more safer plugin?  So, the first question is for finding vulnerabilities in WordPress itself.  So, yeah, basically, I think it depends on my mood, my current mood.  Sometimes, I try to find directly some of the known functions,  like the excite, or the follow function, or the call user function.  So, yeah, sometimes I do that and then trace back to the source of the input.  And then sometimes I'm also trying to find it directly from the global variable itself,  like the GET, POST, REQUEST, and also like the SERVER.  So, I think it basically depends on my mood,  whether I'm trying to search from the source or the SYNC.  But mostly I am searching from the source.  For the second question, sorry, can you repeat the second question?  This is not about security research,  but do you feel any way to choose a safer plugin?  I mean, how can you guarantee that,  relatively guarantee that this plugin is more safe?  So, I think there is no simple answer to this,  because, yeah, as you can see in this slide,  we are demonstrating a critical vulnerability in a very high installation count of plugins.  So, yeah, we cannot make sure if the highest count installation of a plugin is much safer than others,  but the availability will be much more than before.  And it probably has a better quality,  because mostly the huge installation count of the plugins is developed by a big company,  and it has a lot of developers on it, and it has some checks here and there.  So, yeah, I think the most safer way to choose a plugin to use  is I think based on not only the active installation of the plugin,  but maybe try to check if the plugin has previously addressed the vulnerability in a good timing manner.  For example, in previous cases, they patched the vulnerability in like 3 days or 4 days,  rather than the plugins that take a long time to patch the vulnerability.  Thank you.  Any more questions?  Sorry, I can ask, why you prioritize something like XSS SQL injection over something like RCE?  What's your reasons for doing so?  Yeah, so for the priorities for vulnerabilities itself,  so yeah, basically, mostly the priority is built towards the PHP code itself.  So in these cases, I am first prioritizing the previous escalation,  because this is like the most impactful part of the environment.  Of course there is like RCE, there is also like a critical one,  but it is not many plugins that use custom command call or something like that.  So our previous escalation is the top priority for the vulnerability in WordPress.  For the second one, the XSS, as I stated previously,  because the behaviour of WordPress and the current behaviour of WordPress,  if we receive a signal XSS from WordPress,  we can basically create any user, any role, including the XSS role.  So in WordPress currently there is no additional security type in place  if you are creating a user, so you can just basically create a user using XSS.  So yeah, maybe there could be like an enhancement in WordPress itself,  so when you are creating a user, you can ask for like password confirmation,  or like a notification, but basically for now, WordPress doesn't have that type in place,  so basically you can receive the XSS.  For scaling the chain, of course, there is a priority to extract data from the database,  and also the 4th month PHP update injection, because it's in PHP,  so you need to find the PHP update injection.  And then RCP and LFI also, because it's in PHP,  and then the last one is arbitrary file rate injection.  Why arbitrary file rate? Because with this you can read the WP,  that's for particular PHP file to find some interesting data that is credentialed.  Is there anything else? I think that's about it. Thank you very much.  Oh, one last question. Sorry.  In one of the CEP, you mentioned that it affects, I think before 6.3,  so how do you make that connection? Do you test a different version,  or somehow you remember through experience?  Yeah, so for this case, yeah, so the vulnerable part itself,  I think it's partially from the plugin side, and also partially from the WordPress core itself.  So in this case, they both, the page and the book, from the plugin and the WordPress core,  so in the WordPress core, it is not, it is not, we cannot anymore perform this.  So you call it before 6.3, is it? Or you test?  Oh yeah, so yeah, I'm first testing the bot and the plugin itself,  and then I notice that the plugin is using the built-in function,  built-in prototype of admin body classes in the WordPress core,  and then I check the function, the function part itself in the WordPress core.  So it turns out that the implementation in the WordPress core itself is not secure,  so it can be solved by any success.  All right. Thank you, Rafi, for any other questions, you can take it off stage.  Thank you. Yeah, I just want to say that,  so since this is my first presentation, if you have a good deck,  you can give it in the link below, in the slides,  and you can use it more often.  Thank you.


url: https://www.youtube.com/watch?v=Mw6iCqjOV9Q
title: Off-By-One 2024 Day 1 - GPUAF Using a general GPU exploit tech to attack Pixel8
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=Mw6iCqjOV9Q",
    "title": "Off-By-One 2024 Day 1 -  GPUAF   Using a general GPU exploit tech to attack Pixel8",
    "description": "Abstract\n\nLast year, we developed an advanced exploit technique capable of transforming a conventional out-of-bounds (OOB) bug into a more potent exploit primitive, specifically a page Use-After-Free (UAF). Utilizing this technique, we successfully exploited a vulnerability in the Pixel series, achieving Kernel Code Execution.\n\nThis presentation will commence with a thorough examination of the component where we identified eight vulnerabilities, all of which were patched this year. We will delve into the root causes of these vulnerabilities.\n\nSubsequently, we will demonstrate how we applied our exploit technique to convert one of these bugs into a Page UAF (PUAF), and subsequently construct a physical memory read/write primitive on a Pixel 8 with Memory Tagging Extension (MTE) enabled.\n\nFurthermore, this talk will address the challenges we encountered during the development of this exploit, highlighting the differences in exploitation techniques between the Pixel 6 and Pixel 8 models.\n\nSpeakers\nPan Zhenpeng (@peterpan980927) is a mobile security researcher at STAR LABS SG, focusing on Mobile(iOS/Android) and Web security, he was the speaker of Zer0Con, POC, OffensiveCon, 0x41Con and HITB Armory.\n\nJheng Bing Jhong (@st424204) is a security researcher at STAR LABS SG, focusing on Linux, VM and mobile security.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2138,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   Today, everyone, today we will research into a top-level GPU exploit technique to target  the PSoS kernel.  GPU-UoF, short for GPU-Patch-Level-Use-Factor-Free, represents an approach to exploit vulnerability  within the PSoS kernel.  In this presentation, we show that how GPU can exploit from a limited vulnerability,  transform into a full and complete exploit.  Hi, I'm Billy, currently working at Star Labs.  I am focused on the Linux kernel and Android kernel.  Hi, everyone, I'm Peter, currently working at Star Labs.  I'm focusing on iOS and Android kernel.  Today, we will focus on two areas, ARP analysis and GPU-UoF exploit.  In this introduction, we will briefly discuss how modern Android kernel can protect the  attacker from a privileged escalation.  First, we will examine the recent ARP report, their root cause and demand, and the patch  to enhance the system security.  Next, we will explore the GPU-UoF exploit, understand its mechanism, the vulnerability  exploit, and how we can get rid of the lost modern protection.  Finally, in the conclusion, we will summarize our thoughts and their implementation on our technology.  Our research focuses on Android 14 with Linux kernel 5.10 and up.  Privileged access network and privileged execution network protect kernel space to intentionally  access and execute from the user space.  UAO uses SS override against the common address limit override.  PSE is a security feature that addresses and encrypts calls to the pointer to verify their  security and prevent control for hijacking attacks.  MTE is a hardware-based security feature that adds memory tags to each data wall to detect  and mitigate memory-safe vulnerabilities such as buffer flow, overflow, and UAF errors.  KSALR is a security technique that recognizes the location of the kernel memory to prevent  memory-based attacks, making it harder for the attacker to predict the memory layout  of the kernel.  Configure initial stack or rerun to initialize everything on the stack with a rerun variable.  Configure initial allocative OR to initialize everything on the heap with a rerun.  Configure debug list to check the linked list activity.  Select free list random, then pick a patch from the free list to prevent easily heap  overflow, and some other independent mitigations that Samsung cannot anticipate.  UAO is a notable mitigation for the address limit issue involving overriding unprivileged  load, store, and instruction, typically used in a function like copy from user and copy  to user, when in the kernel DS.  Before the introduction of the UAO, operations like the run to the kernel buffer followed  by the read to the user spec will function normally.  However, with UAO enabled, this scenario will change.  Run to the kernel buffer is unaffected, but read from the user spec will trigger a fault  due to the privileged access scenario.  MTE memory tag extension has support in the KSAL app, represents one of the most powerful  mitigations available against memory-based attacks.  By running the setProperty command, user can enable MTE.  Many blocks have been mentioned already, such as MTE execution.  Essentially, MTE function is a hardware-supported sanitizer, capable to detect and mitigate  memory-safe vulnerability.  Even in the event of a fault during the check, MTE will cause the kernel to crash, but the  target process will be killed.  This configure is a way to enhance security in more presentable use of virtual addresses  for the cache or ROM.  Similar to the ROM BA sequencer feature found in iOS and macOS, this approach ensures that  the virtual addresses are pinned to the special cache or ROM region, with the physical memory  only recycled during the compilation process.  Implementation of this feature will significantly mitigate the risk of the fault cache or ROM  exploit.  Secondly, it is worth noting that this feature has not yet been introduced on the Android  platform.  This configure is to introduce multiple general-use cache for each size.  Similar to the KMLK type found on iOS and macOS, KMLK updates by the KMLK to one of  the multiple caches.  This approach reduces the success rate of the hit-or-run bugs.  Specifically, enhance the security.  This feature has not yet been enabled on the Android platform.  Cannot detect a physical cache, and enhanced SES networks could be a major security mitigation  in the Android ecosystem.  KNOW-ELO2, performed at a high-hypervisor level, provides a security-execution environment  while defending only a long-run-to-do operation in the file list.  Physical cache, as well, redundantizes the physical memory layout against memory-based  attacks.  Additionally, enhanced SES networks that use more restricted policies or disable kernel  configurations.  SES networks deliver, make kernels always enforced and could not be disabled.  Many researches have uncovered exploit privileges within the kernel mainstream, particularly  targeting the vulnerability such as write-on-the-read-only-page bugs.  Violations liberate structures like a structure buffer in a 30-page attack, or spring user  control data into the kernel structure, including the type data page, SK-bundled data and AIO  page.  Additionally, there is a considered interest in exploiting vulnerability alone or obstructing  physical rewrites by compromising the page table.  There is also an introduced target amount research in target GPU bugs.  However, it is necessary to consider whether the GPU can be exploited by the bug or literally  outside of the GPU itself.  A large GPU vulnerability used in the wild has been detected by the corporeal link as  shown in the picture.  Let's start at the bug analysis.  We recently do research into the bug hunting, a hardware device used by the Kerala subsystem  user for a certain purpose.  This device, accessed through the device LWIS by a system user with Kerala health contents,  has been associated with the page table highlighted in the resource security printing.  We decided to give it a shot since we are new to the Android.  Here is how we uncovered.  During our bug hunting, we discovered a denial-of-service vulnerability residing in the LWIS IOControlHandle  command packing function.  This vulnerability arises from the usage of the file loop to copy IOControlMessaging links  from the user's back.  Such an implementation leaves the system vulnerability to explode, potentially leading to the DOS  attack.  By manipulating and using the linked list to point to the expel, the attack can trigger  a dead loop, resulting in a system-free and unresponsive state.  We have identified another bug named IntegerOverflowVulnerability, which is a prepareResponseLock function.  This vulnerability occurs when calculating to see if the maximum value of the integer  can be represented.  Where the TransactionResponseBuffer was allocated based on the overflow response size value.  LWIS process transaction in the queue is invoked by another kernel thread, leading to the call  to process IO entries, which triggers an outbound SS issue.  To address this vulnerability, the patch involves incrementing a check step to check the read  buffer size before allocating memory for the read buffer type.  Verify the read buffer size before allocating, the patch presents a potential integer overflow  or outbound SS.  An outbound SS vulnerability within the LWIS InitializedTransactionBase function.  This vulnerability arises due to the failure to properly initialize certain transaction  structures, such as those created by the structure TransactionFromCommit function used from the  CopyFromUser function.  This vulnerability, from the fact that the value of the InforTriggerConfigurationNumber  node, which determines the number of nodes, is entirely controlled by the user.  A tech can use this value, potentially lead to an outbound SS and memory compilation issue.  To enhance the LWIS InitializedTransactionBase function, it adding a chain to keep the number  of nodes under the sum estimate value, if the number of nodes is type size, which cannot  be a whole additive value.  I think there is no need to check for the active number.  After the contractual transaction from the commit function, the canSenseTransactionValue  node is used and is sanitized.  Immediately after work, perform another sanitization check, once it is successful to ensure the  integrity and security of the transaction data.  We also have discovered a vulnerability in the LWIS AccomplishedFetch function, specifically  considered as a type confuse.  This vulnerability arises from the pursuit of the file type without properly verification.  To address this vulnerability in the LWIS EndingCompletionFetch function, to evoke type  confuse, a patch has been written.  This patch evokes to modify the structural LWIS fetch to include a new field name, structural  ID as a possible file.  By introducing this new field, the patch to provide a clearer indication of the structural  type.  Then, directly access the LWIS EndingCompletionFetch field as a patch.  The patch introduces a chain to the structural ID field.  This chain ensures that the structural being patched as a patch is correctly identified  by its structural ID.  Next, Bangden, Peter and Yu.  I will explain the next four bugs and exploit techniques.  Bug 5, this issue shares the same cause as the previous integer overflow, but is from  a different calling path.  Both entry.readWriteBatchSizingBytes and info.numL entries are user control values, which can  lead to an overflow of the read buffer size.  This patch mitigates the read buffer size overflow by checking in each loop if adding  the readWriteBatchSizingBytes to the read buffer size will cause an overflow.  If an overflow is detected, the process will bail out and return an overflow error code.  This type confusion bug shares the same root cause as before.  It directly converts the 5-pointer private data to a specific struct without verifying  its actual type.  Additionally, although there is a check to see if the LWIS FenceFD and the FenceFD are  the same, this can be easily faked and lead to further harm.  Since it shares the same root cause, Google now uses its newly designed function LWIS  FenceGap to perform the root type check based on the structure ID and FenceFD.  This approach is more robust and harder to bypass with a different type of private data.  And bug 7 is an uninitialized bug in the constructTransactionFromCommand function.  The kTransaction variable is allocated from kmerk from the kernel heap, while some fields  in it will later be used and they are never initialized.  The transaction variable here is actually passed from the previously allocated kTransaction  and the nonTriggerFences field is not initialized since the nonTriggerFences is an integer type.  So if it initializes with a negative value, it could bypass the highlighted check here  and cause an auto-unaccess.  However, the config on pixel 8 reveals that the kernel is compiled with init all zero  mitigation, ensuring all stack and heap memory is initialized to zero.  Therefore, this cannot be exploited under the current config.  Nonetheless, other models without this config remain vulnerable.  And I'm not sure which specific commit patched this, but after emerging from the Android  15 DB branch, the kzalloc replaced the kmerk and this change ensures that even without  the init all zero mitigation, the bug cannot be used.  And the final bug is the third type confusion bug caused by not checking the real type.  It happens in the LWISTriggerEventAtWeek transaction.  The preconditionedFenceFB here was added in the week transaction by fget.  It seems okay for now because the preconditionedFenceFB is still a general structure.  And later, this variable is used in the loop within the LWISEventTriggeredConditionReady.  In a specific case where the info.triggerCondition.triggerNodes.eventCounter is equal to the LWISEventCounter  on next occurrence, it will directly take the preconditionedFenceFB's private data  and translate it to the LWISEvent without further checks.  A fix involves replacing the fetch with the LWISEventFenceGet, of course, same as before.  And additionally, it cracks the inaccurate error code return.  And next comes to our exploit part.  Here I will introduce a general exploit method and use one of the bugs we discussed before  to get the physical memory read-write on PixelSeries.  So in the mobile market, there are three main types of GPUs with its own driver,  the MediaTek's Mali, the Qualcomm's KGSL and Apple's own GPU driver,  and each used by different brands and models of phones.  Although PowerVR GPU is there and I think they are not as popular as these three in the mobile market,  so therefore not discussed here.  These GPUs share same functionality but implemented differently.  For example, they both support memory allocation from the GPU driver, but name is different.  Like Mali uses the KBaseAPMM analog, KGSL uses the KGSL IOControlGPU analog,  and Apple uses the C++ device user client new resource.  And the difference in the Apple GPU name arises from the unique driver framework called IOKit,  which is the C++ subset.  And of course, all these GPU drivers support importing memories from the CPU side.  And Mali uses the function called KBaseAPMMImport,  and KGSL uses a flag called MAPFLAGSUSECPUMAP in GPU-alloc functions.  As well, Apple uses the same function routine, just specifying a field called IOServiceID in the input struct.  And technically, the shrink-layer interface is not specific to the GPUs.  It's a mechanism within the memory management subsystem that allows for the freeing of cached items,  so their memory can be repurposed.  In Linux, various drivers and subsystems will register their own shrink-layer callback functions,  and when the system is low on memory, these functions are invoked to release memory back to the kernel for other use.  In the case of GPUs, we can leverage this mechanism to shrink memory and create a page-user-free primitive.  And page-user-free is a strong primitive in Xbox.  It can allow us to fake kernel objects from the user space, or fake the page table to read and write arbitrary physical addresses.  Many mitigations are based on virtual memory, like KSR, heap isolation, and read-only mappings.  If we can reuse the page as a kernel object, or even page tables,  we can easily bypass those mitigations and get a kernel-arbitrary read-write.  After reviewing the GPU mechanism, it seems it can give us such a primitive,  and here we will dive into Mali driver for an example.  In Mali, the structure kbase-v8-region represents a GPU memory region.  It contains the attributes for CPU and GPU-side mapping.  In the alloc function routine, Mali will use kbase-mem-alloc with a user-space-passed flag  to alloc memory and return the attributes to the rep variable, which is the kbase-v8-region.  In the free function path, it will use the user-provide-gpu-v8 to find the rep structure on the arbitrary maintained kbase context.  If the memory region is valid and not free, it will free the structure as well as the memory region represent value.  If the memory is invalid, just log error and bail out.  After knowing it's allocation and free, we can dive more into the structure itself.  Here we can skip those irrelevant parts and only pay attention to the flags and the kbase-mem-physics alloc in here.  Flags can show this region is free or not, and the attributes is read-only or read-write.  And we can see there's two structure kbase-mem-physics alloc in the kbase-v8-region.  It represents the physical memory mapped to CPU or GPU when mapping it.  So the struct kbase-mem-physics alloc is a physical pages tracking object and its reference content.  The k-reference will record the number of users of this alloc.  The gpu-mapping will represent the count number of times mapped on GPU.  For example, if we alloc a region in GPU, then we alias it this region, it will pass one for the alias operation.  As for kernel-mappings, it's same like gpu-mappings but you record the CPU-side map times.  Then comes to the next, it's the number of pages that is valid.  Actually, there's other fields will be interesting in exploit, but here is what we need for the tech.  More, the structure kbase-mem-physics alloc is an elastic object in the general snap patch.  And the size is the base, which is the size of alloc plus 8 multiply the pages.  And the pages is controllable by us.  We can see from the red line place, it will use the calculated object size to alloc the memory from kzalloc  with the gap-kernel flag, which is also general for using.  And one of the IO control called kbase-mem-commit can help us to reach the shrinker function.  But to trigger the shrinker, we need to fulfill some requirements.  First is gpu-mappings of our memory region should be 0 or 1.  And the kernel-mappings should be 0, means a region that only mapped in GPU-side once  and never mapped in CPU-side can be shrinked.  Otherwise, it will cause a side effect.  Then the shrink new pages need to be less than the old pages to let us enter the kbase-mem-shrink path and shrink the pages.  And after the background knowledge expanding, we will introduce the exploit we use here.  So if we first allocate the native page from GPU and align this region, the gpu-mapping field should be 2.  And since we allocate it in GPU and not imported by the CPU, so the kernel-mapping is always 0.  Then we could use the bug to override it to 1.  And then we trigger the kbase-mem-commit on it.  GPU will shrink the page and return it back to the main pool.  After the page is recycled, we will still hold the handle point to the free page by a large region.  That's turned out of bound.  Relative to a stronger page use of the free page.  Another thing is the GPU mapping is usually less than 256.  Which means we just write one byte and achieve this.  After we have the UAM page, we need to read and write from it.  Because we hold the large region handle, which is the GPU virtual memory region,  we can only issue the GPU read and write request to Debian.  One of the ways is to use OpenCL.  OpenCL is a framework for writing the programs that execute across platforms like CPU, GPU, DSP, FPGA,  and other processors or hardware accelerators.  Programming language we use for above-mentioned devices is based on C99, C++14, those standards.  Another way is to reverse engineering the GPU instruction set.  Luckily, we don't have to do that ourselves.  Thanks to the Panverse project.  And the IO control for running GPU instructions is the KBase IO control job submit.  Each job contains a header and a payload.  The type of the job is specified in the header.  And the job type write value provides a simple way to write to the GPU address.  After knowing how to read and write the UAM pages...  I think we're being attacked by GPU.  We need to know how to reuse the pages as an other object, like path struct or page tables.  When we allocate memory from GPU, we first allocate from the KContext mempool.  If insufficient, we will allocate from the KBDevice mempool.  If also insufficient, we will allocate from the kernel.  And the free process is like the same sequence.  We first add the pages to KContext mempool.  If the mempool is full, we add to the KBDevice mempool.  If also full, we free the remaining pages back to kernel.  To exploit it, we have two options.  Option one is to reuse it as GPU PGD.  In the structure KBase MMU table, we can see there is a PGD field.  It represents the physical address of the page allocated at the top level of each table of the context.  In fact, every context maintains their own GPU MMU translation table.  And the KContext pointer is pointing to its corresponding KBase context.  Just like every user space on the CPU side will have different address space.  And in function MMU.getNextPGD, which is called when we try to access the GPU memory.  If target PGD is not accessed before, we will allocate now by the KBase MMU allocate PGD from the KBDevice.  Then it will add the new allocated PGD to PTE.  You may wondering why here is like set PGD to PTE.  Since on CPU side, the PGD is the page global directory that manages PMD and PMD manages PD.  But I think here is just naming problems.  So we don't need to confuse about this part.  We can consider the PGD we talk about next as the PTU in CPU.  As the code shown before, most address are unused.  PGD and PTE are only created when they needed for an access.  So the page that inspecting PGD is allocated from the KBDevice mempool.  And which is shared by all KContext.  Which means with proper mempool function, we can reuse our free pages as GPU PGD.  So our step will be first reserve page for spraying PGD later.  And arrange the memory to fill up the free list.  Then we spray this KBaseMemPhysicAllocStructure and trigger the outer bound to overwrite one of the GPU memory.  After KBaseMemCommit shrink and free the page because KContext mempool is full.  It will return to KBDevice mempool.  Then we allocate some free pages again which we previously reserved.  And we will take the memory page we just freed into the KBDevice mempool as the PGD of our new allocated pages.  After we use UI page as GPU PGD, we can make GPU virtual address point to arbitrary physical address.  By reversing firmware, we can calculate to know kernel global variable physical address such as AC Linux state or code pattern.  Use GPU write to modify the AC Linux 0 to disable AC Linux.  Even config static user mode helper path is read-only on CPU.  But we can mark it as read-write in the GPU PGD.  And we can overwrite it with BeanShell.  Then we overwrite code pattern to the payload we want to execute by BeanShell.  And finally, trigger the segment 4 to trigger the core dump to exploit payload in the root bridge by the code pattern tree.  Next, I will pass the bidding for the option to exploit.  As we mentioned before, if the next pool does not have the space, KBase allocate page is used to allocate page directly from the kernel.  Similarly, in the free case, when all pools are full, return the page back to the kernel, create an opportunity for reuse as another kernel object.  We can then reuse the free page as another kernel object to continue the exploit.  There is a type of way to achieve kernel address rewrite.  The exploit scenario involves several steps.  First, we will reserve page in the GPU for later allocation of the PGD.  Then, we use impulsory to position a KBase memory physical allocation structure behind the LWS translation response buffer.  Trigger an integer overflow to overwrite the GPU memory.  And then trigger the memory coming and find out the UAF page.  Allocate the reserved page and reuse the UAF page as PGD in the GPU.  Use a latency handler to modify the page table entry to point to the physical address we want.  We can disable X-initialize app, limit the competent trigger to get root, and launch a virtual shell for example.  When we try to port our exploit on the PISO app, we encounter the issue to use a latency handler to modify the PGD point to the physical address.  On the PISO-6 device, the KBase IO-control job submit IO-control can be used to write to the GPU memory.  However, on the device featuring the CSM competent system feature start from the PISO-7 generation and above,  this specific IO-control may not be compiled or available due to the change of in-system architecture.  In this scenario, where the KBase such IO-control is not available, we can resort to use OpenCL GPU memory rewrite operation.  Here we can approach it. Use the DLSIM tool and let me point out the necessary functions from the OpenCL library.  Initialize our GPU rewrite function. Use the gpurewrite.cl file.  This contains the required OpenCL kernel and function for the memory access operation on the GPU.  This approach alone performs the GPU memory rewrite operation without the KBase IO-control job submit.  Thereby, maintain the physical and access the different device modules and software versions.  So we can work our rewrite into the C support.  Indeed, use the OpenCL introduces another problem.  Due to its automatic create a new memory file descriptor and manage its own GPU address page table.  Attached to write to the memory created by the OpenCL, use a different file descriptor will result in page 4 on the GPU side.  For more, both screens in the OpenCL FD will break our CPU function, prevent the reuse of the UF page as the PGD.  So we use a shell library known as convent tree to hook the OpenCL function.  For set up the device and reserve the screen page can ensure the capability with.  By interpolate and modify the name of this function, we can reserve the necessary page before GPU opens CL.  The memory object cell can contain a region of memory and its different objects.  Besides caused by the shrinker mechanism, we can use KFreeze to achieve page UF.  Qualcomm GPU or PowerVR GPU should have the similar memory object as Mavic GPU.  The exploit properly deploy on the shrinker mechanism to achieve properly escape from the page UF.  Without directly engage MTE, the initial outbound as if it detect may trigger a KSL or warning in the deep messenger.  Potentially hold the exploit flow.  And the chance of detecting the outbound is low from our test, less than 50%.  Offer a chance to execute the exploit flow and up the root access.  We can run the exploit a few times to expound the root shell.  And we can connect our root messenger in the deep messenger.  Then we can show the device demo that we use to GPU technique exploit for the integer overload.  Okay, so...  So here we can see that MTE is enabled and the AC Linux is enforced.  And we trigger the exploit and it quickly pop a reverse shell back above.  And we can see that we are the root bridge and AC Linux has been disabled.  Okay, so this is our final part.  We will do some conclusion based on the previous sharing.  Mitigation is sometimes hard, it may be weak from another level.  We should think other supports and defeat mitigations by our boosting features.  And targets not only have vulnerabilities but also can be part of our exploit path.  And with more and more software and hardware mitigations,  exploit 1.0 is harder but with good exploit package is still possible.  And finally here are some references we use when we prepare the slide.  And you can refer to it.  And above is what we share today.  It's supposed to be the Q&A session but I think our time is left.  We are still around.  If you have any question, you can come and ask us.  Thank you.  Thank you.


url: https://www.youtube.com/watch?v=2Amrq7ydU44
title: Off-By-One 2024 Day 1- Universal Code Execution by Chaining Messages in Browser Extensions
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=2Amrq7ydU44",
    "title": "Off-By-One 2024 Day 1- Universal Code Execution by Chaining Messages in Browser Extensions",
    "description": "Abstract\n\nBy chaining various messaging APIs in browsers and browser extensions, I demonstrate how we can jump from web pages to \u201cuniversal code execution\u201d, breaking both Same Origin Policy and the browser sandbox.\n\nI provide two new vulnerability disclosures affecting millions of users as examples. In addition, I demonstrate how such vulnerabilities can be discovered at scale with a combination of large dataset queries and static code analysis.\n\nSpeaker\nEugene Lim is a security researcher and white hat hacker. From Amazon to Zoom, he has helped secure applications from a range of vulnerabilities. His work has been featured at top conferences such as Black Hat, DEF CON, and industry publications like WIRED and The Register.\n\nIn 2021, he was 1 of 5 selected from a pool of 1 million white hat hackers for the H1-Elite Hall of Fame.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 1906,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   Great.  Can you guys hear me?  OK.  OK.  Great.  Yeah.  Thanks for coming, guys.  So I know I'm the last session for today.  So I'm kind of in a wake, but hopefully this  is useful and entertaining for you guys.  Part of the talk title is Universal Code Execution  for ByteChaining Messages in Browser Extension.  And this was kind of inspired of two things.  Firstly, I think the conference organizers really  wanted some web talks.  And it's kind of hard to think of a good web talk  in a zero-day kind of bound research conference.  So I was trying to do something different.  And the second thing is that I really  like client-side attacks.  I think it's interesting.  It gives you an opportunity to test,  do more white box and gray box stuff.  And that's kind of the reason for today's research.  So I'm Eugene.  So I kind of blog at this.  It's based on a food dog that I am a security engineering  lead in a day.  So I do good stuff for the government.  And we are hiring.  So just my little show for today.  And hacking is my hobby.  So I do like researching after hours at night.  And this is kind of one of the little projects  I worked on back then.  And so for today's talk, I'm just  going to go through a quick outline.  I'm going to give you some background and prior work  on extensions research.  Especially, I think, one of the more updated parts  is Manifest V3 and the Web Extensions API internals.  And I'm going to talk about the first part of the chain, which  is from postMessage to sendMessage.  So for those of you who are more familiar with web-based  attacks, you know that postMessage  is a client-side attack.  And how do I kind of bridge that gap from a web page out  of the sandbox into the extension context?  And the second part, I'm going to talk  about quick finding that in extension A,  just to illustrate how this can be exploited.  And then I'll go to the next part, which  is a bit more interesting.  How do you then cross the bridge from the browser extension  context to the desktop native context?  That's from sendMessage to sendNativeMessage.  And how that has changed with Manifest V3  from prior research.  And then I'll talk about extension hunting and scale.  So I think the part is, how do you then  scale this research across millions or hundreds  of thousands of browser extensions all at once?  And that's kind of one of the things  that I think is more exciting about this research.  And I'll talk about code execution in extension B.  So you know that these are not real names.  Unfortunately, I disclosed them in April.  But I don't know if I've patched it yet.  But I thought it would still be interesting to go through  and show you a video of the experiment.  And I'll go to the conclusion and further research.  Cool.  So let's start with some background.  I think some of you may have heard  about universal cross-site scripting.  And they probably have the most powerful exercise.  And why is that?  Because it's not a vulnerability in the web page,  not in the HTML, not in the scripts.  It's a vulnerability in the browser itself,  or in some cases, extensions.  Because people kind of use extension vulnerabilities  to trigger that.  And what this means is that the XSS triggers on any page,  regardless of what kind of scripts  are in the DOM of the target website.  So as long as you visit somewhere with a malicious website  or maybe it's part of the URI.  Recently, I think there was some really cool research  in the macOS Safari universal XSS.  You can check that out.  And then the JS is executed in the context of any website.  So it's no longer limited to one exit, one website,  but any website.  And that makes it almost like a same-origin policy bypass.  OK, we'll take it one step further.  And while I was actually halfway through my research,  I had an unfortunate experience where  you kind of search what you've been doing.  And you realize someone has done it a little bit before you.  And as early as 2017, researchers  have looked into extensions and have  found a lot of weaknesses.  So I think this is something that was presented  by Ed Waas in 2017.  Looking at the post-message security of extensions,  how do you bridge the gap from a web page  to the browser extension context?  And then we'll see how much has changed since then.  2017, the spoiler alert is not much.  It's still exploitable.  It's worse.  Somehow there seems to be a problem pattern these days.  So let's start with some background.  Browser extensions comprise of new key components.  The first is the manifest.  They tell you exactly what's in the extension.  It tells the browser how to interpret  the rest of the extension parts.  The second is the content script.  This is scripts that are injected into the web page  by an extension.  So how the extension can interact with your DOM,  if any web page that you give the permissions to.  And the second part is the background script  or the service worker.  Background scripts were used in the manifest v2.  The more recent manifest v3 uses service workers.  The main difference is that service workers are short-lived,  but you can still make them last a bit longer.  And finally, we can talk about the native messaging calls.  Some of you may use password extensions,  maybe use 1Password.  And you've always maybe wondered how the extension  can talk with your 1Password app  that you installed on your desktop.  This is how it does that.  And we'll investigate that a bit.  So let's do some code review.  So firstly, the manifest declares a few things.  It declares the service workers, the content scripts,  and more importantly, the content security policy  and permissions.  And there are a ton of boot camps available  where developers can make mistakes  or have overly permissive permissions.  One of the key things is...  Let's see if we can highlight that.  One of the key things in manifest v3  is that you no longer have a background script.  You have what we call a service worker.  This is what you define as the script that runs  in the browser extension context.  The second thing is the content script.  The content script is what's injected  into a web page by the extension.  Because sometimes the extension may need to interact  with your document object, although you don't.  What's on the web page may need to insert something,  read something.  And one of the fun things is that  you're not supposed to actually inject  the content script in every single page.  You're supposed to specify what URL  that you would then inject the content script into.  But what I've seen is that  a lot of developers just don't care.  And they set it as either all URLs  or they have a lot of content scripts  that appears in every single page.  But the great thing about all this  is that it makes it really easy  for you to identify potentially vulnerable extensions.  Because you can have this starting point  where you see manifest  and you parse all the manifest  to figure out if it may be something  that you may want to dig into a little bit.  So, the second part is content scripts.  So I mentioned that you can inject scripts  into any page, right?  Or extension.  Of course, that does sound a bit scary.  And that's why, actually, my extensions,  they are injected into what they call isolatables.  That's Chrome's terminology for that.  Basically, even though you inject it into a page,  it can access the DOM,  the document object model,  but it cannot access other JavaScript variables  like scripts that's running on a page  or even other content scripts.  A second thing with Manifest V3,  Manifest V3 is basically  the latest generation of extension specifications,  is that there's very strict  default contents-aside policy.  So it prevents most of the inline  JavaScript execution in XSS.  This was a big problem, maybe about five, six years ago,  where the extension would read something  on the DOM, on the document object model,  and then it would devalue it  and devalue to XSS at the extension browser context.  But this has been elevated a lot  by a strict default CSP.  And also, there's a limited browser extension API  available to the content scripts,  not the full browser extension API,  but just enough for them to talk with the background script.  So I'll talk about that.  So as I mentioned, the content script  that's injected in your page can't do a lot.  It can read the DOM, it can insert, change stuff.  I don't think they even make a fetch  unless you give it sufficient permissions.  So most of the time, for more complex functionality,  what they do is that they pass messages  to the service worker that's running  in the browser extension context.  So the content script will execute  chrome.runtime.sendMessage.  There are multiple APIs that allow them to communicate back.  And what the background script will do  is then take that message, do something with it,  and if necessary, call back to it  by just sending the message back  to the port or the subnetwork.  In this case, you can just look for addListener,  one message, very simple,  not very complex way of content message passing.  There is also cross-extension messaging.  It's possible in some extensions,  but it's fairly rare.  So most of the time, what you'll see  is a background script talking sendMessage  back to the content script and vice versa.  But you can see that the context is all kind of separate.  So it allows them to stay safe in isolated worlds.  So let's talk about the first part of the chain today,  which is the postMessage to sendMessage.  And to communicate from a page.js to the extension,  postMessage is used in the shared DOC.  So what do I mean by that?  Say, for example, you have a web page  that is supposed to interact with your extension  that you've installed.  Maybe you've installed a one-password extension,  and you're visiting the one-password homepage,  and maybe they kind of want to talk to your extension  when you're visiting the one-password homepage.  How does it do that?  Because, as mentioned, in the DOM itself,  there are isolated worlds in the JavaScript context,  so they can't actually talk to each other.  But they can both access the DOM.  And one of the great things that you can do with it  is then send a postMessage to yourself.  So the website will make a postMessage call to itself.  And this postMessage is actually able to be picked up  by both and all of the content scripts on that page as well.  And so this is actually a pattern that's recommended  by the Chrome documentation, where it's like,  hey, if you have a web page that you want to talk to  your extension, use the postMessage pattern  to talk to it.  So what you do is that you send a postMessage to yourself,  and the listener, in the isolated world of, say,  content script 8, will pick up that postMessage to itself,  sometimes with some validation, like making sure  that it's really from the same page.  And that's how you get that message from the DOM.  However, one of the things is that postMessage  was never really meant to be used like this.  I mean, you probably know that postMessage  is a pure browser client-side API.  It's just for frames to talk to one another  sometimes across origin.  It's never really meant to be used in the extension context.  It's kind of janky, but that's how we are able  to have that separation in isolated worlds,  but still share the same DOM.  And this means that typical ways of validating  the origin of a postMessage are now nullified  with weak manifest matches.  So in this case, for example, what you typically see  in a pure client-side pool with no extensions  is that you validate the event source  and make sure that it comes from the same window.  So it's like, OK, it's either my parent or a child window  or my own frame that's talking to myself.  It's not coming from another origin  that is trying to talk to me.  In the case where you're using this in a pattern  of page postMessage talking to the extension content script,  this is actually useless because it doesn't actually matter.  It's always going to be the same.  So now you can bypass that.  And this makes it even more dangerous.  And as I mentioned earlier, this is effectively nullified  when you have weak extension matches, manifest matches,  where the content script is injected in every single page  regardless of your DOM.  So very quickly, we can talk about a case study  with extension A.  And in this case, it has a very weak matcher.  You can see it here.  It has a few permissions.  It has a cookies permission.  And it can access the cookies of website A, website B,  and all the subdomains of website C.  So obviously, I think it was meant to just operate  on all these websites, but the matchers doesn't line up  with what permissions it's in front of.  So in this case, how this works is that we would have  an addEventListener on the web page,  in the content script.  And on receiving a postMessage,  it would actually forward it to the background script  using the chrome.runtime.sendMessage.  That's how it talks to the background context.  And in the background script, which is running  in the browser extension context,  it will get the listener.  It will check whether the action is a specific action  to this endpoint.  In this case, getCookie.  It will execute getCookie, retrieve it,  and then send it back using chrome.tabs.sendMessage.  And this is really super simple, straightforward exploit.  You'll see this a lot happen in more weaker extensions.  So this is something that you can exploit very easily.  It just runs on any domain.  So as long as you have this extension installed,  as long as you're visiting your payload  regardless of domain, you can then  get cookies of website A, website B, website C.  And this brings the same version policy.  So this is one of the extensions installed  by more than 300,000 users, and very simple to use.  We're still on very well-known ground here.  Most people looking at extensions would see this.  So let's talk about something more interesting.  How do we extend this exploit from just the same origin  bypass, policy bypass, to something more interesting  where you have a browser sandbox breakout?  Not exactly a breakout, but it's kind of an app-level breakout.  And that's by going from sendMessage  to sendNativeMessage.  So how does your one-password extension,  and again, one-password is not the application  that I'm talking about.  Don't worry.  You can keep it.  How does your one-password extension  talk to your desktop application that's  installed in your desktop?  How this is done is that there is a part of both the Manifest  V2 and the Manifest V3 browser extension  APIs called native messaging, where native applications can  register native messaging codes, which is just  a binary executable running using a manifest file as well.  And so for Chrome, you can register it at this registry key.  And you just tell them, this is the location  for this application of myManifest.  And in Manifest itself, you specify a few things.  Of course, you specify the host name, which in this case  is myApplication, and then the path  where the Chrome will help to forward those messages to,  in this case, ChromeNativeMessagingPost.exe.  And there are a few other additions  where you can add a lot of origins.  In this case, Chrome extension, which Chrome extension  can actually trigger this standard input.  They have a type of the input.  But actually, it's just standard idle,  which I'll talk about a bit later.  But this is basically how it's going to communicate.  It's going to be standard in, standard out.  Very simple.  Typically, just string JSON and Google Input.  So in this case, background scripts can then,  or extension service workers, in the case of Manifest V3,  communicate with this native application  host via the browser.  So this is very similar APIs, but for native messaging.  The second thing is just, as I mentioned,  just use a standard in and standard out.  So it's very simple parsing.  You don't really see very complex encoding.  Most of the time, it's either Base64 or just JSON.  It's just in text.  And if this message is handled dangerously,  then the native application can be exploited.  So in this case, we would see a very simple pattern.  Again, from the Chrome documentation,  this is running in your background script  or your service worker.  So in the browser extension context,  not the content script.  It will send a message to the host with your text.  And it will also be able to listen from it  to receive the output from your native host application.  And this is something that you can then string together  to get what we, you know, it's just a term,  a universal code execution.  Think of it as similar to universal XSS,  but in this case, you're making one more jump  from the browser extension context  now to the desktop code application context,  which means code execution, right,  outside the browser.  We start with step one,  where your browser extension has a wildcard pattern  for content script.  So it's kind of weak.  Not super necessary, right?  You can run on certain websites.  You can find all of it on your web page as well.  Put one more link in your chain earlier on.  Second is that the equal web page  or the injected script  then sends a post message to itself  in the same frame, right?  And in this case, the content script will be listening.  It will be able to pull that post message  and it will pass that message on  to the background script using sendMessage.  The background script gets that message,  it does some stuff with it,  and then finally forwards it  to your native host application  using sendNativeMessage.  And then, of course, the native application  handles the message dangerously,  leading to code execution.  So you might think,  okay, that's cool, right?  It probably only happens to  one or two web applications, extensions.  There's a lot of parts of this chain  that need to do that to work.  So let's talk about extension planning at scale.  I'm not going to go and look at  every single extension out there one by one  and try to figure this out.  So we can do this at scale,  and this is kind of one of the fun parts  of boundary research these days.  You can scale it using  whatever pipeline you have.  So there are a lot of  existing databases  that make it easy to query  browser extension manifests at scale.  One of these is the  Chrome extension manifest database  on GitHub.  It has a dataset of more than 100,000 extensions,  and basically this guy scripts  all of the manifests for all of the extensions  he could get his hands on  for you to make a query with.  It has quite useful scripts  for you to then parse all of this data  at scale, because you can use  breadth or  jQt,  but it's  going to be kind of not necessary  if you just use the script.  And then you can add a few filters to that.  So in this case, what I started with was that  hey, I want to find  extensions that may be used by  a lot of people, and I'm going to filter  whether they have a content script,  whether they include a permission that includes  native messaging. So there are two parts  of the chain that are available for me,  and there's some likely people  that are disconvinced about it.  So after filtering for  promising manifests, I would then  download and extract the extension, and then  scan them with a custom sender code,  because remember there are two other parts  in this chain that you want to connect.  The first part is the postMessage handler,  and then the second part is the sendNativeMessage  function.  And this is something you can do with the tools available  these days very easily at scale.  My favorite here in this case was SendRep.  You can use the TaintSource and  TaintSig, and then just do  a standard taint analysis at  scale across maybe how many  manifests that you've filtered down.  In this case,  I look for a few things.  I look for either ChromeRuntime.sendMessage,  or I search for port.postMessage,  because there are multiple ways  that you can express sending a native message  in the extension.  For pattern sources, I also had to  add a few more  filters. In this case, if you  use SendRep before,  you recognize focusMatterVariable,  patternNot, these are ways to just make sure  that I don't get false positives.  And so I think just with  large enough funnels,  you will always get results.  So I started with more than 100,000 extensions,  and then I did the quality-to-filter  potential manifests, in this case  of 200-plus.  And then by running my SendRep rule, I can then  narrow it down further into  31 service workers' background scripts  that seem to be vulnerable.  And followed by that, I kind of have  to make sure the last part of the chain is available,  which is manual review of the native force  application binaries for exploitability.  In this case, you start seeing  a few interesting patterns with the types of  applications  that would use this kind of pattern.  In this case, I found something  with PKI card extensions,  and I'll talk about  why that is.  So, let's start  with the case study here with  extension B.  Extension B is used by more than 2 million users,  and this is an extension that  kind of fills a common gap in browser  extensions, in that it adds PKI  smart card support in browsers.  As you may know,  the browsers, a lot of them don't  support PKI smart cards by default.  They support the Web App  standard, so that's  fetal pass keys,  but they don't support PKI smart cards.  The problem is that there are a lot of enterprises out there  that still use PKI smart cards, and  this is why extensions are very popular.  In this case, they have more than 2 million users,  but I'll tell you that this is not  the only extension that has this pattern,  that has this number of users, because everyone  kind of wants to fill the gap.  And by design,  in order to enable PKI card support  on whatever web page you use,  by design, you're going to have to have  a wildcard extension  match it. In this case, as you see,  they just use a star for the key,  the URI, and the path as well.  And fairly standard,  you can see that they have permissions for  page and messaging.  So let's try to link this up  all together. We'll start with the content script,  and what the content script does is  again, that it checks, I mean, they try  to be secure. They check whether the event source  matches the existing window,  which, as I mentioned earlier in this presentation,  is useless, right? Because once you have  a wildcard matcher, the event source  can be any page that you control.  And so you can send a message to yourself,  that's always going to pass the origin check.  The second thing is that it forwards  the event data to the background  with the sendMessage API.  The background script as well,  again, it does a few checks.  It checks for the action type,  but it doesn't really do much  more than that, so it immediately forwards that  to the open native  messaging port via the  chrome.runtime.connectNative  that is open previously.  And of course, your native host application  passes the standard input  as JSON, and then it  just, well, you can tell  this is just one of the actions that it  runs to load the DLL at the  provided value that is given  in the message.  So since native  messages are standard input,  it is really, really easy to identify  the entry point.  Again, this is part of the code  that was the handler for this.  What it does is that it just takes  the argument from your  native message,  parents it to C Windows System 32,  and then loads the DLL at this part.  And this is a very common traversal pattern  for DLL loading, not complex at all.  I'd just like to show that  I think Winston, you're here.  My former colleagues,  we worked on a C-scale client  that also had  DLL loading that  is interesting, so go read that.  But  other than requiring a known value path,  it's not overly complex, fairly simple,  and something that  I think for most attackers, you should be able to  run.  So in this case, what do you need to do?  You first need to trigger the download of a malicious DLL,  and then send a postMessage payload  that would then trigger  the native post application to load  and execute the malicious DLL.  Standard, I mean, you can use the DLL hijacking,  but in this case, it's not a DLL hijacking.  So it's a simple two-stage POC, as I mentioned.  The known download path  is an annoyance, but often native post  applications have very inexplicably  weird features like  getInfo or getUsername.  You see some weird things  in this space.  One of the side notes is that  there are some browser extension  APIs that allow you to specify  the download path and trigger a download  anywhere in the computer.  So keep an eye out for that.  In this case, the POC  triggers the download payload.  It just creates a form  and a link and clicks it.  This is a bypass that most people  use, because in order to trigger a download,  browsers make sure  that you have to click something  or have some kind of user interaction.  This is one way to quickly simulate that  using JavaScript without any user interaction.  The second thing is  you send a post message.  In this case, you have to add some  standard values that will help you  get around the various checks  of both the content script  as well as the background script,  as well as the native  post script.  In this case, we're going to select  an action, and we're going to specify  that I agree it's going to be in your  download folder and the payload  that you specified.  Okay, so  this is kind of what it looks like.  So again, I've given you  the extension, but  I don't have the function names.  It triggers the download for the payload.txt  and it's going to  pop the calculator.  This can be run on any page  as long as you have this extension installed.  You were hoping to use a smart card,  but I think you had a different surprise  that day, but this means that  your bar will rebalance when you visit.  You can inject it anywhere.  It's very simple to exploit.  There are even some features that inject the content script.  It's also fairly easy,  i.e. if someone is using this  extension that you want to exploit.  Okay, I'm just running out.  I'm going to talk about the conclusion and some of the  learning points for this.  As I mentioned, this is something that was  maybe raised a few years ago  at MacFest v3  for Chrome extensions, browser extensions,  MDM  also. MDM defines this  as MacFest v3. It was meant to  improve the security of browser extensions,  but this was mostly in  the client side where they added content  scripts and also limited  permissions to request  or even execute the browser APIs.  It seems that  powerful browser extensions  are a feature of the cloud.  I know there's been a lot of work  in browser extensions, especially in  critical space, primarily because of  Metamask and other similar  extensions, but it's really  hard to secure Chrome extensions.  For researchers,  it's great because  they are the white box in research  by default, so you have access to all  the code and you can analyze it from there.  They are built in  at every level.  For example, as I mentioned, with the  PKI card extension,  just because my  definition of PKI card  extension needs to run on any website,  they're going to have a wildcard extension.  There's a poor understanding  of risk posed by  extension permissions and messaging  chain. As mentioned, I  did a fairly strict  where I filtered  100,000 applications, but this  was because of professional time and  the CFP was coming up and I needed  to get a result quick. But if you  extend this a little bit bigger  in terms of what kind of  sources and sinks that you're willing to tolerate  as well as whether you're going to spend  some time to maybe  find a bug on the website instead of a wildcard  origin, you can actually find a lot of interesting  things.  There's poor understanding of risk by developers  of having this through train  a kind of a  pass-through from the content script  to the background script and finally to the  native host application.  What I see most of the time is that  there's a lot of trust at the  native host application level  of the messages they're getting from the Chrome extension.  Primarily because for native  host applications, the manifest  allows them to restrict messages  from a specific Chrome extension  and  most of the time, it's going to be there.  Another interesting thing here is  that just by  understanding that there is this  vulnerability in your native host application,  you are now also very aware of  the fact that  even if it's not coming from a Chrome extension,  this application  is vulnerable and it just needs to take it from  standard in. And this leads  to very interesting questions of  is this extension running in a very  privileged context? Is it a password  manager? Is it running as  a privileged user?  And this does happen,  especially for these kind of extensions  that need that interactivity  between the browser and the desktop.  And it's  still very under-researched. So I mentioned  as early as 2017, people have been  thinking about this, but  there's a lot more research that needs to be done in  Manifest V3 APIs.  Manifest V3 brings about a new set of APIs,  new set of permissions, restrictions,  but it also lets a lot more experimental  features, such as maybe credential  manager API. There's  some side work I've been doing on Web  70PM APIs,  but that's still in  exploration. So yeah, that's  it for the chain.  You should all get my hiring  properly. But if you  want to find out more, I'll put up a blog post  that summarizes the learnings  from today and on my blog.  So thank you very much.  Thank you, Eugene.  For the last session of Day 1,  we open the floor for any questions.  First question from Trevor.  Okay, so  have you monitored any  or observed any similar  type of issues in  communications in the WebSocket area?  Because there are also some  extensions we could have done  asynchronous communication instead.  And it's totally  different, but the delivery is still the same.  So have you  observed any of that?  I think that's interesting.  Mostly because the post message was the  recommended pattern for  page  document object model to  content script communication. I think  WebSocket might work. That's why I was interested in  Web70 as well, seeing if that's something  that opened up a channel between  content script and the page  document object model.  I have not looked as much into it, but it's definitely  one possible path to expand  the public cloud approach.  Thank you, Eugene.  Any other questions?  All right. Excellent.  Thank you very much.


url: https://www.youtube.com/watch?v=508ng3J1FgI
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
title:
  Off-By-One 2024 Day 2: Keynote - Pwing to Action How Offense Helps Us Improve Security: Eduardo Vela

content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=508ng3J1FgI",
    "title": "Off-By-One 2024 Day 2: Keynote - Pwing to Action How Offense Helps Us Improve Security: Eduardo Vela",
    "description": "Abstract\n\nIt\u2019s too easy to find problems in software today. Not enough people understand how attacks really work, and this is bad for defense. Both attackers and defenders need this knowledge, but we are always busy fixing today\u2019s problems.\n\nThere\u2019s not always enough time for making things stronger long-term. In this talk, I share how my teams have used offense to make defense better. We use weaknesses and exploits, study how they work, and then use this data to help organizations decide how to move forward.\n\nWe\u2019ll discuss using exploits to prioritize patches, motivate process changes, and ultimately create systems that are more resilient. Sometimes, we offer money to break things in new ways \u2013 and show us where to focus, sometimes, we turn on the heat on a broken system so it transforms into something better.\n\nThis is not always about fancy new insights, ideas or attacks. It\u2019s just about working together to make systems safer for everyone.\n\nSpeaker\nEduardo breaks things for a living, mostly the digital kind. Leads a team of Google\u2019s finest bug squashers, manages disclosure drama and spends an unhealthy amount of time poking at software and hardware in the name of science teaching them new tricks (that they really shouldn\u2019t be able to do)\u2026\n\nAims to make the digital world a more or less terrifying place, one exploit at a time. Eduardo often wonders why anyone trusts him with this much responsibility.\n\nHe\u2019s pretty sure this is due to a combination of luck, caffeine, and the fact that he\u2019s surrounded by people far smarter than himself. But hey, he\u2019s not going to question it too much.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2044,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240831"
  }

  This text was transcribed using whisper model: large-v2

   OK, so thank you for the introduction.  My name is Eduardo, as I was introduced last.  And, oops, what is this?  Hopefully this works.  Oh, there we go.  Perfect.  That's me.  I work at Google in the Information Security Engineering team.  And mostly what we do is things related to making Google products safer.  And recently I spent a little bit more time, as he said, on CPU and Firefox.  And the things that I want to talk about today are related to the ways that we have been approaching,  the way that we did things internally for Google products to the outside world as well.  So our dependencies and open source and hardware dependencies.  Technically, what I do at Google is things related to vulnerability stuff,  mostly related to vulnerabilities found manually by people.  I don't do it.  We have a large team, but I manage one part of the team.  So, yeah, I was trying to make an agenda, but it was very complicated.  So I decided to summarize it as something else, which is simply a goal,  which is trying to write down how keeping exploit information secret makes offense cheaper,  defense more expensive, and how we, as part of developing more secure products,  are trying to reverse this trend.  And this is one of the reasons why we are here today  and why we like to engage with the security community, offensive and defensive.  I want to start by explaining more or less the information asymmetry example  with a very classical example you might know already.  These are four cars.  These four cars are all, from the outside, they look the same,  but one of them has bugs.  One of them has problems.  I hear that in Singapore it's very expensive to buy cars, actually,  but imagine this from a world where people buy very cheap cars.  From the perspective of the seller of the first car,  they want to sell it for $50,000, let's say.  I don't know if they are a good car or not, but let's assume it is.  The second car, the person wants to sell it for a little bit more, $55,000.  The reason is they both think that's how much their car is worth.  The third person thinks it's a little bit cheaper.  They want to get rid of it faster.  So they sell it for $49,000.  The last person, the one that knows they have problems in their car,  they can sell it for less, a lot less,  because they know the car has problems.  But the buyer will not know the car has problems until a lot later.  So they also can sell it for more expensive, because why not?  People will be like, I want the best car, and they will just...  You know there's these people that just go sort by price  and then get the most expensive.  This is bad, right?  This is bad for consumers, this is bad for users,  this is bad for everyone.  This is mostly depending on how much people are willing to pay for things.  People are willing to pay depending on the information that they have.  The average price for a car of this size is $52,500.  I just added it all and divided by 4.  In the scenario that I gave you,  let's imagine that the average price of a car is $52,500.  There is one car that is buggy out of five cars.  But then another person with a car with problems decides,  oh, that's actually a pretty good deal,  I also want to sell my car,  and they will add one more car to the mix.  So now there are two cars out of six.  And that will lower the price to $50,000.  Now the problem is that  now it is not worth it for some of the people without good cars  to sell their cars anymore.  So they might remove themselves from the market,  which leads to two out of three cars having bugs.  This is just generally an explanation,  it's called a market problem,  and it's a general scenario of how information asymmetry  from the buyer and the seller can result in market collapse  and no incentives to improve.  So, generally speaking, how could we solve a problem like this?  Any ideas?  AI.  Artificial intelligence?  Yes, maybe.  Maybe transparency as well.  So, good.  The way that I want to express this is that  the way that we react to security problems nowadays  is mostly as if they were a fire, or an incident,  or something that requires immediate attention,  or immediate response.  But that has the consequence of  after you are finished with the incident,  then you have maybe a slightly bad reputation,  a slightly worse product, slower, whatnot.  And that is technically not the best way to react to problems,  it's a very expensive way to react to problems,  and it is generally not good for your business,  or for your users.  A more generally better way to deal with security problems  is better to think about it as a medical, medicine problem,  which is like, rather than eating, you know,  free third-party dependencies from Node.js,  Polyfill.io, and all of these very tasty, high-calorie treats.  You might want to do better,  maybe things that are not as tasty,  like memory-safe languages,  or maybe do things that have a clear dependency graph,  and things like that, like verifiable legal systems.  And that, generally speaking, is difficult,  like it makes it, it's less appealing,  but it's complicated work.  Same for behavioral changes,  like maybe instead of launching things  without testing in production,  low coverage of testing, and so on,  maybe you have to make lateral changes,  like code reviews, or unit tests,  or continuous integration, and so on.  And all of these type of changes,  from one thing to another, are expensive.  Are expensive for developing features.  It increases development time,  which are things that developers have to worry about.  Developers have to worry about many, many components  of the things that they are working on.  Like, for shipping features in time,  it could be development time,  it could be the maintenance of the features that they have,  it could be the latency of the applications that they run,  bugs that are functional bugs,  that are introduced by accident,  maybe performance,  they want to make sure that the applications that they run  look and feel fast, and are fast for the users,  as well as capacity,  maybe there's not a lot of RAM in the cell phones,  maybe there's not a lot of storage on the database  to be able to run this.  And generally speaking,  all of that is what developers are thinking about  all the time.  So when you say,  oh, we want to add some additional features,  like lifestyle changes,  or dependency changes,  then you are essentially adding time  to their development time,  you are making them take more code,  you are adding latency,  you are adding more bugs to work on,  you are adding additional performance issues,  and you are requesting more capacity.  So all of that is difficult for you to be able to sell,  unless you have a good way to measure it.  So going to something a little bit more technical,  or back to something that maybe is easier to grasp.  So can someone spot the bug in this?  Where is it?  Here.  Do you have it?  Yes.  In this, which line do you think has the bug?  It's a very simple bug,  but this is just an example.  Any ideas?  The what?  Okay, I will not stand there.  Fascinating, okay.  The what?  On which line, yes?  Yes, exactly.  So this filter here is the very simple use of the free.  The way it works, very quickly speaking,  is that you have a very simple structure,  the structure has an allocation,  somewhere in memory,  in this case I decided memory 4000,  it sets the first field to 666,  then it frees the memory,  so it is given back to the allocator,  then it goes back,  another structure is allocated,  it reduces the last time structure of this allocation implementation,  it sets it to zero,  and then something is reducing the memory address from before,  that is supposed to be zero,  and it modifies the value,  and then instead of being zero,  as you expect,  and here what happens is that you have two memory addresses  that are pointing to the same thing.  Now, this is a very common, simple type of bug.  There is a simple fix to all of the use of the free bugs  that you can implement today in your application,  which is you go to the libc function,  you find libc free,  and then you return immediately.  This is 100% effective,  and it works the following way,  you have the same as before,  you free it,  and when you allocate again,  you get a new address,  and that's it, no more use of the free.  The problem with this is that  if you run this twice,  you start using more and more memory,  until you have so much memory,  that you run out of memory.  This is not great,  but it fixes the use of the free.  So the question, generally speaking,  will be here,  is it worth it to fix use of the free?  Now, it depends.  This actually was an extremely useful mitigation  for CTF in DevCon,  where you're allowed to do binary debugging,  binary patching,  and they just modified one,  like the allow function,  with, I think, A2,  well, they just changed the pointer,  so that it was essentially allowed.  And for them, it was worth it, right?  Like, they get flags for opt-in,  and the machine was,  any time that there was out of office,  it would restart.  So, out of memory, it would restart.  So then it was actually pretty good,  for their use case.  But, if you want to run this  on your own organization,  it probably would not work out.  So the general question is,  how to calculate when is it worth it,  and when is it not worth it.  So, earlier on,  I was mentioning the example of  responding to issues as an incident,  as an emergency.  One way that seems to work,  or at least historically has worked for us,  is to look at the costs that  responding to an incident costs.  So, for example,  lost sales or partnerships,  or features that you couldn't launch.  And then you just ask,  or you let the people ask themselves,  how would you spend to respond to an incident?  Like, you look at actual data,  like what actually happened in the past.  And you will have three,  generally speaking, levels.  Like, how much is the hypothetical maximum  you would want to spend,  the amount that you actually spent,  and if you had implemented  certain security obligations,  how much you would have spent otherwise.  And let's say with these three categories,  you have over time,  you brought it over time,  how you expect them to change over time.  So, you can expect that  you're going to have,  at the rate of introduction of bugs,  you're going to have more bugs like this.  Or you can expect that,  on the other hand,  that if you implement certain mitigations,  maybe things will get better over time.  And you can use that  as a mechanism to approximate.  Here's an example of the Chrome security team,  or the V8 security team,  how they are looking at  comparing two types of mitigations.  One is disabling the JIT,  the just-in-time compilation sample,  just-in-time compilation of JavaScript code in V8,  versus the V8 samples,  which, if I have time,  I will go into later.  Generally speaking,  the two examples here  are looking at previous data.  They are looking at  inter-world exploits,  V8 CDN,  which is a setup  in which we pay people to write exploits  for vulnerabilities in V8.  You actually can participate.  You don't have to find the bugs.  You can just pick a bug from the bug tracker,  and then implement an exploit for it,  and you get paid some money for it.  The other one is Pwn2Own,  which is a bit more hard to participate,  but you can participate as well.  There is one part of it  that is interesting,  which is the in-the-wild one.  As you can see now,  thanks to V8 CDN and Pwn2Own,  there is actually more data  than there would be  if we only relied on in-the-wild exploits.  If we only relied on in-the-wild exploits,  then we will have way less information,  and we might reach the wrong conclusions.  As you can see,  there is some sort of a trend  on JIT compilation being actually  very, very effective  in general,  but not so effective  compared to in-the-wild exploits,  versus sandbox bypass,  which is generally speaking,  effective as compared to the other.  The more data that the V8 security team has,  the easier it is for them to defend  or invest in different areas,  especially in mitigations  that have some amount of development costs  or maintenance costs,  like the V8 sandbox test.  I want to shift a little bit  into the in-the-wild area  that I'm talking about here.  The one way to think about it  is that because of  the way that technology  is affecting our lives right now,  it is very common for everyone to use it,  including good guys, bad guys,  all types of guys and girls,  and the law enforcement  and intelligence community  are struggling to keep up with this.  The way that they are...  10 years ago,  James Comey, the FBI director,  was calling for backdoors for encryption,  and at the end of the day,  he made a very compelling argument  about why law enforcement  needs this information.  However, one of the things  that happened at the end  is that the...  One of the things that happened  after all is that we have the...  government, intelligence community,  become another participant in the market  for CODX.  However, it's not just law enforcement,  it's also military use.  And it's not just the military use  of one country,  it's the military use of multiple countries.  This is just like continents,  but you can imagine.  And it's not just law enforcement  from one country,  it's law enforcement from every country.  And it's not just law enforcement,  it's also investigation.  It's also not just that,  it's also bad guys,  folks like cybercriminals and so on.  Generally speaking,  you can think of every time  that someone is trying to reach,  let's say,  the treasure,  every time someone is trying  to split the pot or whatever,  they will try to take multiple paths.  And the more paths that are taken,  the less likely it is  that they will take the same amount of area.  Simply because from a perspective of  you have to select to go right or left,  you have to select,  you might assume that something is hard,  but actually it's not hard.  And depending on your previous experiences  and your skills in certain areas,  you might choose different areas.  Leading to multiple types of  reaching the same end result.  Which, at the end,  looks something like this.  As you can see here,  the top two folks took the same path  at the beginning.  But then almost everyone else  went the different way.  And then when a defender is trying to  figure this out,  they have a better knowledge of the system,  so they will take the most straight path.  And the most straight path  might not always be the most effective.  One will probably be the most effective one  to stop all the other actual adversaries.  For this case,  let's say that defense sets up  a couple areas,  a couple mitigations on the way,  but they actually are not that effective  against real adversaries.  Generally speaking,  you can think about this as a form of cost.  So, in the same scenario that  offense needs a certain amount of information,  defense needs to know as much information  as offense to be able to have a fair fight.  However, it becomes more expensive  because there is more demand  and there is more competition.  And it also becomes harder and more expensive  for defense to afford this information  simply because they have less supply.  And the reason they have less supply  is because it's harder.  So, it just becomes more expensive.  So, the general concept is  how to increase offense  without increasing defense costs.  And we can also use artificial intelligence,  but in this case,  we can say it's transparency.  And generally speaking,  the idea is that  by publicly talking about ways  to solve these very difficult technical problems,  we can attract offense to use those problems,  those mechanisms.  And they don't have to,  but they can.  Because from their perspective,  they can use what is going to work.  But then, this will also make it easier  for us to make it worth it  to invest in certain mitigations.  However, as soon as you start investing  in these mitigations,  then people will start choosing  the other path.  They will be like,  okay, I'm not going to use the path  that you know is going to be detected.  Then you use the other one.  But then it just becomes a money problem.  Then you have to decide  do you use the very cheap path  that comes for free,  or do you choose the more expensive path  that you have to figure out yourself.  And this also becomes a problem  in the case that  if there is a lot more information public,  then the vulnerability clusters,  the exploitation techniques and primitives  are also likely to be...  They are not infinite.  They are limited.  So the more people  that are publicly talking about this,  the more likely it is  that you're going to have duplicates  and you're going to have collisions,  and it's more likely that  things are going to eventually get shut down.  So then from the perspective  of talking to research,  you have going from one defender,  if you are talking with the public,  then you have many defenders  that can balance the situation.  As a form of comparison,  you can see what we did for the current CTF.  This is the number of public kernel exploits  according to multiple sources.  I duplicated them and added them together.  And you can see in 2016  when DirtyCow came out,  there was a big interest spike.  And then since then,  it kind of went down.  Then we started launching KernelCTF,  and then that started going nowhere.  So now we have more kernel exploits public  than we ever had before.  Another thing that we're trying to do with this area  is to go from the current status,  where we have quite a lot of very expensive,  it is very expensive to get this information  because it has much competition,  to a situation like hopefully in the future,  let's say 10 years from now,  there is a lot more researchers,  a lot more people that are able to do this  just because it is a lot easier.  The barrier to entry is not so high.  And also, hopefully,  we are doing a good job with mitigation.  It's also a lot harder to do reliable exploits.  And it's also harder for offense  to profit from this scenario.  So in the ideal long-term scenario,  the ideal scenario would be  that it goes from the current scenario  where it's very profitable to do offense  to something where it's not so profitable to do offense.  Of course, it's never going to cross like this.  This is an ideal scenario.  So the idea of all of this presentation  was to try to break down  why keeping information secret  made offense cheaper,  different from offensive and reversing the trend.  And the premise is that  with transparency,  buyers can differentiate more secret products,  which means that they can demand better  from their offenders.  It also allows defenders to quantify their mitigations,  and by the way,  increasing the cost of offense  and lowering the cost for defense.  And hopefully this whole mess  that I presented at the beginning  kind of makes a little bit more sense.  And I don't know how much time I actually have.  So...  I...  I don't know how much time I have.  LAUGHTER  APPLAUSE  Thank you, Eduardo.  I think we have some time left for Q&A.  Anyone have any questions?  Hey, so speaking about  making it more expensive for attackers  and cheaper for defenders,  when are you rolling out MiraclePointer in Chrome?  Where is MiraclePointer?  I didn't mention MiraclePointer.  That's so sad.  I thought I did.  I ended up choosing something else.  I think it's already there,  but I'm not sure if it's enabling  all platforms.  As far as I know,  it's enabled in some platforms,  but not in all of them.  Or maybe it's enabled in all of them.  I'm not sure.  Is it not enabled in all of them?  It's enabled in some of them, for sure.  But there's a chance that it is in  some obscure, architecturalized problem.  Hi, thank you for your talk.  The part about the market forces  disrupting the industry, more or less.  From your experience,  from Google's context,  does increasing bug bounty  actually help disrupt the market  for the offensive security side,  or is it counterproductive  because the prices are high?  From your experience,  should Google increase bug bounties  for our CEs, et cetera?  I think it depends on what you do  with the information.  Once you have a bug bounty program,  when you increase the prices,  you most likely are going to receive  more reports.  But then, if you don't do anything  with the reports that you receive,  then, well, then nothing happens.  There's going to be the same amount of bugs.  So, maybe this is a good way to think about it.  So, if you have renewable bugs,  so if the bugs that you fix  are slower than the rate  that you're introducing them,  then it's irrelevant how much you pay.  But if you are removing bugs  from the code base  faster than they are being introduced,  then it is more likely  that you're actually making an impact.  So, I would imagine that  if you are increasing prices  without doing anything with information,  then it is not going to disrupt anything.  But if you are,  even with a small amount of information,  if you're doing something about it,  then, yeah, you will eventually make an effect.  But you usually need a lot of information  to be able to make good investment decisions.  And the investment decisions  usually are very expensive.  So, that's why more information...  Usually, that's why...  So, for KernelCDF,  we increased the rewards 10 times  from 10,000 to 100,000.  And the reason was  because we needed a lot more information  than we wanted to have.  Hi, thanks for your sharing.  Yeah, I think I briefly saw your slides.  I think it wasn't covered in the main sharing part.  Like, in your appendix,  there was a slide on rewriting Binder  from C to Rust.  Actually, for my school project,  I had a project converting C code to Rust.  I think it was pretty difficult.  I just wanted to know your thoughts  about moving forward  with the conversion to Rust, right?  With everything supposedly memory-safe.  So, will you fully eliminate  this class of memory bugs?  What are your thoughts on it?  Yeah, so, one of the advantages of Rust  is that it definitely...  And not just Rust.  Rust, and Golang, and even Java.  Like, they remove certain type of problems.  And there is...  One of the things that I wanted to mention  in this slide that I didn't...  It's a map of slides.  Is that you can eliminate problems.  And by eliminating problems,  or class of problems,  you are...  This is the most effective way  of improving security.  Just by eliminating the problem.  And yeah, Rust eliminates that problem.  And it is, however,  the most expensive thing to do.  So, re-implementing code  is highly difficult.  And even from the...  I don't think I have the code here, but...  Well, I have a part of the code.  But if you find the patch series  that Alice posted on the Linux kernel  maybe this...  She actually goes into talking about  the trade-offs of rewriting code.  And actually, the first sentence  of the commits of the patch series,  of the intro letter,  was that this is usually the last thing  that you want to do.  But it is worth it for certain scenarios.  Especially in something as critical as Binder,  that is accessible even from sandbox processes.  That was very important for them to tackle.  Also, it also had other reasons.  The code was very hard to maintain  because it was very complex.  And there was a lot of technical...  So, yeah.  It makes sense for them to do it.  Okay.  Hi.  So, I tell you, I ask...  So, I really like the fact that you presented  the trade-off analysis  on how increasing certain variables  would decrease the cost of defaults.  But is there any practical studies  or statistical studies done in Google  that really shows that there's  a statistical significance in these areas  that you guys have explored?  Or is it just based on observations?  Yeah.  I mean, I think it's interesting.  To be able to find enough data,  we would probably need  a couple hundred years worth of information.  So, maybe in a couple hundred years.  But the number of vulnerabilities  and exploits that we have  and information that we have  is coming at such a slow rate  that it's mostly something  based on principles.  But we will only be able to  essentially measure it with error bars  and degrees of freedom and so on.  Once we have enough data  that the amount of error rate  is easy to measure.  But that would take a really long time.  I think it's probably possible  for certain types of bugs  that were super common  were well studied.  But whether to say...  There's also problems about  what you can measure  and what you cannot measure.  It would be hard right now  to be able to make that.  But it's something we looked into.  Or at least I looked into.  But it's not immediately obvious.  At least for certain parts of it  you can actually do.  So, for this part,  the rate of introduction of bugs  versus...  At least for the bugs  that people know how to find,  you can see how that goes to zero  if you make certain changes.  I mean, it becomes obvious.  If you're protecting the use of the free bugs  and then you're switching to binder,  you will have no more use of the free bugs.  And then that, of course,  it goes from something to zero.  It's very different.  But, yeah.  To be able to do a general analysis  that says that in general,  for every possible case,  this will work.  They will have statistical significance.  That would take a very long time  to be able to have that.  The market is good though.  Alright.  Great talk. Thank you.  I was curious if you had any thoughts  on increasing the access  or the transparency  in having all these end days  effectively visible.  It's obviously a trade-off  because there's going to be  cyber criminals and other people  who now have access to these  and then time to patch.  Very apparently with Android  and also many other platforms,  it's pretty long.  Under a number of months,  if not years,  for weird edge network devices  and stuff like that.  I was curious if you had any thoughts  on what the trade-off of  this increasing transparency  versus people having a lot more access  to easily applicable end-day chains.  I think the problem here is twofold.  One of them is increasing the time to deploy.  Sorry, increasing the time to deploy.  The time to deploy would be  once the bug is public,  how much does it take  for it to reach the user?  That increases or decreases  the shelf life of the vulnerability.  You are correct that  if an exploit is public...  By the way,  all of the kernel CTF submissions...  There is a Linux kernel exploit  for pretty much any kernel  always public in our world.  Yeah, there is definitely a...  Hello.  Oops.  Hello.  Can you hear me?  I can't hear you.  I suspect this is the next talk.  Anyway, I'll try to quickly finish this.  The time to deploy is...  Okay.  Can you hear me?  Yes, I can hear you.  Okay.  All right.  Time to deploy.  Yes.  Generally speaking,  if the number of bugs was...  If the supply of bugs was very limited,  then I would agree that  disclosing the few bugs that exist  and an exploit for them  would have a very equal effect  on the market.  However,  with the assumption that  the bugs are easy to find  and are very diverse,  then the trade-off would be  whether to have more information  to be able to accelerate progress  or to restrict it to be afraid  of it being used very well.  This is different for cases  when the software is open source,  like the Linux kernel,  where actually the community  needs to know this information  to be able to make timely changes  versus when the code is not open source,  and then the only people  that can equally make a difference  with technical details are SQL.  In those cases,  it's still useful to have transparency  from the perspective of metrics  and exploitation paths  that might allow the user  to understand how to protect themselves  despite whether there's action or inaction.  But yeah,  that is the trade-off.  The trade-off is mostly about  what information do we make public  and when,  and what considers unreasonable risk.  Unreasonable risk being risk  that is unexpected  versus risk that users are  understood and expect  that will come from them.  Generally speaking,  the only way that we can reduce  the patch cap,  the patch cap being the time to deploy,  is if we put pressure  as consumers on the manufacturers  that give us this code  to create the mechanisms to update  and to do it quickly.  They will never do that  if information is skipped away from the users.  I guess the aspect is  the more information we can provide  to provide pressure to the market  to deliver these results is better.  And this, of course,  creates short-term versus long-term.  Okay.  I think I need to stop  because someone is talking.  All right.  Thank you very much.  Thank you.


url: https://www.youtube.com/watch?v=jcxJy2_sB-Y
title: Off-By-One 2024 Day 2 - AI Powered Bug Hunting Evolution and benchmarking : Alfredo Ortega
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=jcxJy2_sB-Y",
    "title": "Off-By-One 2024 Day 2 -  AI Powered Bug Hunting   Evolution and benchmarking : Alfredo Ortega",
    "description": "Abstract\n\nWhile AI holds promise for assisting bug hunting, its actual impact remains unclear. This presentation addresses this gap by introducing Crash-Benchmark, a standardized evaluation framework for AI-driven static analysis tools.\n\nWe\u2019ll share results from a simple bug-hunting AI agent, AK1, and discuss the implications for optimizing AI-based bug hunting in C/C++ codebases.\n\nAI-bughunting presents unique challenges: Early models lacked sophistication, struggling to comprehend long codebases. Moreover, privacy concerns often necessitate exclusive use of local models, which are inherently less capable than commercial AI models offered by industry leaders such as OpenAI and Google.\n\nTo illustrate this challenge, we\u2019ll showcase AK1, a simple rule-based AI agent capable of autonomously identifying various bug classes within C/C++ codebases.\n\nNotably, its model-agnostic design allows it to improve performance with each new model release. Nevertheless, evaluating the effectiveness of AI-based tools poses difficulties due to the subjectivity of the output.\n\nSpeaker\nAlfredo Ortega is a security researcher and bug hunter, delivering presentations at over two dozen prominent information security conferences globally, including Black Hat, Defcon, Syscan, and Hackers-to-Hacker (H2HC) events, dating back to 2007.\n\nOrtega holds a Doctorate degree in Computer Science from the Instituto Tecnol\u00f3gico de Buenos Aires. He is also the founder and primary architect of Neuroengine.ai, a pioneering platform dedicated to the open-source distribution and collaborative development of open-source artificial intelligence models, promoting community-driven innovation.\n\nAlfredo serves as a Web3 Auditor at Coinfabrik, where he leverages his extensive expertise to fortify the security posture of cryptocurrency infrastructures, ensuring the integrity and reliability of decentralized systems.\n\nFollow Alfredo on X @ortegaalfredo",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2624,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240901"
  }

  This text was transcribed using whisper model: large-v2

   Okay, well in this talk, we're going to speak about, we're going to talk about Clash Bay.  It's a benchmark about the MNX, that is about filling the capacity of the final device.  Because it's unclear if this project actually works, which capacity works,  and which one of the thousands of models actually works better.  So actually, it's a survey of which is the best benchmark, and which one works better.  And also, we're going to make a stand out for Kaggle, that is,  it must be a tool for finding what are the design requirements.  Not a score, just finding the software.  Okay, so I'll do the presentations.  I am Alfredo from Argentina.  I started working in investment development almost 20 years ago.  I used to track commerce before that.  So I never worked in Google.  I did the research.  Of course, half of the page is here, but you don't have to say that you worked in Google.  I like the development of OpenBSD.  The developers know OpenBSD.  It's our brand system that is focused on security.  So the guys that actually made OpenBSD are very, very, very good developers.  They are focused on security.  So to do a tool that actually works, finding bugs,  is better than you testing the best code that there is.  So that's why I mentioned that.  Because I hate it.  Because actually, I think that it doesn't work.  So my demonstration will be using OpenBSD.  Okay, so let's talk about the previous work.  This is very recent.  Because, I don't know, LLM technology is very recent.  In fact, you can see that there is a blog post about OpenBSD just last week.  The very first job of this is from me.  This was presented in Black Hat.  It's already version 2.0.  I think they did a presentation in 2023.  Now it's years again.  It's basically more generic, this one.  It's a more generic view about tasks.  Not only vulnerability-defined, but also protection.  They try to solve CTS problems.  It's more comprehensive.  Now, Google Project Zero actually focuses on trying to exploit vulnerabilities.  Found vulnerabilities and exploit them.  Basically, they conclude that LLMs...  Sorry.  This is the conclusion.  It's not that they fail.  The results are very, very basic exploitation.  This is Stack Overflow with domain protections.  So they conclude that it doesn't work.  I don't say that they are lying.  But I say that this is results from last week.  A week is a lot of time in artificial intelligence.  Let's see what happens.  The Crash Bench is an Infosec event.  Basically, what I do is to assemble a lot of examples from exploitation.  I took the complete...  There are outloads for basketball, for golf, for exercise.  We all started working on extra writing.  We completed each one of these exercises.  Basically, I gave them to the artificial intelligence.  If the IE got it right, it got a point.  If it got it completely wrong, it doesn't have any points.  I also have real vulnerabilities.  I have one from Chromium.  It should be about much more real than with the other hand.  But I didn't have any time, so I only put three.  That is enough.  Also, I did this check only in C.  Surprisingly, the artificial intelligence also works in Rust and other languages.  But this one is only in C.  You configure it.  It's very easy to configure.  You put the prompt here.  The prompt is based on the instruction that you give to the artificial intelligence.  Then, you show every example with exactly the line where the bug exists.  It's very simple.  You show a C source code.  The bug is in line 6.  This is another example.  The bug is in line 30.  It not only checks the bug finding capabilities, but also the reporting.  Because even if the artificial intelligence finds the bug,  sometimes it finds the report correctly.  Sometimes, it says that it's in the wrong line.  Basically, what you have to do is to read a lot of reports.  You have to report correctly.  You have to follow instructions.  Sometimes, it starts rambling.  Sometimes, it's talking about a lot of stuff.  It's like doing research, basically.  Here are the results.  It's a very small font.  Sorry about that.  But there are a lot of models here.  What are models here?  A model is basically every company,  many companies that create artificial intelligence,  release them.  Some companies release them open.  Some companies keep them closed.  For example, ChargerDT is closed.  MoneyMetal is open.  You can go around your computer.  This venture is focused in the local, the open, artificial intelligence.  Why?  Because if you are finding bugs,  you don't want to use ChargerDT  because you are basically giving the bugs to OpenHand  or to Gemini or to whatever,  whatever closed artificial intelligence.  If your AI runs in the closed,  you have to give your code to a third party.  You maybe don't want to do that.  You want to keep your results for yourself.  Or maybe you just don't want your code is related.  You don't want to give it to the AI.  So, many of these results are from local open source AI.  If you want to run it in a computer,  you have to have a very good computer.  We can see,  one of the first results here,  is that...  I'm sorry.  It's very obvious that the better results are from the biggest  and more modern artificial intelligence.  This is Lambda3.  Lambda3 was released a couple of months ago.  So, this is all very recent.  The thing is,  we can see how the artificial intelligence  was increasing very rapidly the capabilities.  This was Lambda...  This one...  Oh, sorry.  This one over here.  This is Lambda2.  So, this was the state of the art just three months ago.  And look at the results.  It's almost...  It doesn't understand anything at all.  The first one is Lambda3,  but it's a very small result.  It's a very small model.  That is basically good for conversation.  But it really can't show that it doesn't understand  or have any idea of the code.  But...  And here in the middle...  Sorry.  We have GPT.  GPT-4.  It's not the best result.  This is very curious.  Why is it not the best result?  This is the most powerful IE.  Well, this is very strange.  So, actually, I'm looking to interpret the results.  And I found that...  I think it's very likely that the...  It's the...  One thing is called alignment.  Basically, artificial intelligence,  it got instructions  that not just speak about certain things.  It can give instructions to make a bomb.  It can make instructions to make an exploit, for example.  It will deny that and all that.  It's called alignment  because it's supposed to be good  in artificial intelligence.  So, the problem with Lambda2  and Open IE  is that it's very strongly aligned.  I mean, it won't give you  the answer of where the bug is  because the artificial intelligence  thinks that you will use it to do malicious stuff.  That is true.  But the IE will deny.  It will say, I didn't find any bug here.  Well, it's obvious that it's a bug.  So, at the end,  the best results are for Lambda3.  Mistral also has  a very good score in this benchmark.  Of course, the benchmark has improved a lot.  But this benchmark  will give you a very quick view  of the capabilities of the systems.  Basically,  the benchmark is already outdated  because  the artificial intelligence found all the bugs.  That's basically what it is.  I had to make it harder  because it's already too simple  for the best application of artificial intelligence.  They found everything.  I had to make more difficult tests.  Now, the quantization effects.  Basically, how you run an artificial intelligence  and you can compress it.  Because artificial intelligence  takes a lot of memory to run  and a lot of hardware to run.  Thousands and thousands of dollars.  And actually it's very slow.  So, you can compress  using a technique called quantization.  That allows you to run  much faster  and a much cheaper computer.  But, of course, it decreases the quality.  It's like a cheap game.  You get a smaller but have less quality.  So, I'm trying to measure  how much you can compress it.  And it's that work that you can see here.  Actually, it didn't affect a lot.  This is like  only 5 bits.  Compression of 5 bits.  Originally, intelligence has about 60 bits.  So, here you can compress  about 3 times with 5 bits.  And on this side,  on this side,  we have 2 bits.  I mean, it's a very, very strong compression.  And we can see that  actually the result, the score,  doesn't decrease a lot.  It goes from 45,  the most, the least increase here,  to about 40.  In the most present.  So, you can use this to  basically, you can compress this model a lot.  They will find out anyway.  They have to be very good.  It doesn't care.  The model doesn't care that much  about if you compress it or not.  This is one of three ways.  I mean, other models  might have worse results.  But this is one of three ways  that they use the model.  And we can see that actually  it's not very affected by compression.  For example,  there is another plot.  Sorry, there's a lot of loss in the presentation.  But,  we can see this plot in the green.  It's basically  the score that they have  in general.  I mean, for example,  you can see that the biggest  in general score,  for example, GPT-4.  Here.  Of course, it's one of the best  in the biggest  finding model.  Here.  It has the biggest score  in general  intelligence,  but not very good  at finding bugs.  Here.  And GPT-4 and GPT-4-O  have the same thing.  And the other  you can see that it's inverse.  For example, this one  has not a very good score  in general answer,  but very good at finding bugs.  Why is this?  I don't know.  But that is the best one.  You can see that  the models that are very strong aligned,  I mean, very strong  in the answer that you can give,  they are very good  at answering generic questions  that are very bad at finding bugs.  Basically, they deny there's a bug.  They basically  they have  limitations  the way they think.  So it's very good  to have a model that doesn't have any limitations.  Okay, so  you can't find real bugs.  You can see.  This is a real bug.  This is from last year.  This is an integral overflow.  Basically,  this is a very simple bug.  Sorry.  The problem with this bug is in two variables.  Basically, it's an allocation size.  It's a  binary size.  It's the  end result of the calculation.  Sorry, it's binary size.  It's the calculation. It ends up in allocation size.  And  this calculation is wrong.  The wrong  integral overflow.  This is the human report.  The interview platform  allocation size, my overflow,  1 and 2. So what happens?  What do the artificial intelligence  give you in this code?  We just see it.  Okay. This is the report  from the artificial intelligence.  I give you the code. I say, okay, find bugs in this code.  And just tell them that.  Find in the rows in this code.  Okay, we can see here  that basically the  artificial intelligence performed perfectly.  It's exactly the same as the human.  End size and allocation size.  That's the problem.  They actually got it.  And after they start rambling  about where the 3 is,  blah, blah, blah, blah. But the important thing is  that the artificial intelligence  performed exactly the same as the human.  And this is a real case.  And it's wrong.  It's one of the most complicated code there.  So we can see  whether the code  actually works with maybe a line.  So maybe we can run the actual demo  here.  Let's see if this works.  This is a demonstration.  So I have this code here.  The issues and  basically I have the code.  It's very complex.  You can see that the problem is in size  and allocation. It's the same  code as before.  So we run this  helper hacker.  Basically, but it's a very simple  code.  You can choose the model here.  This is basically  LamaTree. It's a free service.  It detects how  you want to use your body. It's a test.  Or you just do a launch.  It will take a while  because  it's actually running. It's not running locally. It's running in a server.  Actually it's running in a server in Argentina.  Okay.  So it basically  Well, the first time  we found out that the glyph  is very large, but it didn't found  the vulnerabilities. So what we do now,  we can run it a lot of times.  So we can run it.  Yes, it will. Every time  we will find it.  By the way,  this is not a very good model.  We can try something.  Well, this model doesn't work very well.  Let's try something before.  We have a lot of models to choose from.  QBD4.  Let's see what happens.  I think this is a little faster.  QBD4 tries to speak a lot.  It's running a lot.  Here. All the modularity.  Allocation, size, program,  size. It's exactly the same.  The same reporting  in Argentina. And this was QBD4.  This is actually not the best  model on there. In fact,  right now, we have models that are  way better than QBD4.  We have, for example,  Cloud.  Cloud 2 is much better than QBD4.  And we have  open models  that are actually much better than QBD4.  So, the model actually  started running, but a lot of  problems have fixed the  overflow. It describes perfectly  the vulnerability.  So,  let's continue.  For example,  well,  this is another example of QBD.  So, this is a very,  very...  This is interesting, because  QBD has a lot of fuzziness.  One of the most fuzzy  projects.  And, but,  if we show this code  it will still find bugs.  Because some bugs are very hard  to trigger.  Particularly, this one.  It's a syscall as a heap overflow  in calculation of  this  variable  here.  It will  cause this allocation to fail  and cause an  heap overflow in the kernel.  So, let's see what happens.  We're going to try Cloud. Cloud is one of the best  models out there.  And,  this is basically the problem.  Look for bugs in the code.  And, what does Cloud say?  Well, there's a problem here  in this  structure here, because  this value is  controlled and we can't have some  heap overflow in the kernel.  Right?  So, I gave it  to the OpenVC  developers and they actually  fixed it. You can see  here that it says  that I recorded this line.  We basically just show it in the code.  Even if they have  a version  of syscall from  OpenVC, but it is a very old  bug. It was like 7 years ago.  It didn't  the faster  to find it, because basically  the only way you can find it is to use the technical  because it's very hard to treat.  The artificial intelligence  found it in  5 seconds.  This was a very old artificial intelligence.  It was basically extra. It was like  3 or 4 months ago.  You say, oh, well,  you recorded this. How many bugs  I'm treating now? How many bugs I have?  I don't know.  I don't know.  There's a lot.  The problem with this  system is that  you need to try actually.  The artificial intelligence will record  thousands and thousands and thousands of bugs.  But not  everyone is a stupid developer.  Let's see.  You have to  do this. It's like a fuzzer. You have to go to  each one of them and see  if it works. It actually doesn't work.  But it's much easier to go  to the port than to go to the  gigabyte code. So it actually  makes it work much easier.  The system that I  showed you is very simple.  You just basically delete the source code,  assemble a prompt.  If you want to find a road flow,  a road flow, whatever you want to find,  you just assemble the prompt,  the text file, and send to the model.  And just write the answer  on top. So instead of  seeing the code, you will see the road.  Now, what are the problems  with this approach?  The problem with artificial intelligence is that  sometimes it lies.  There are hallucinations.  Sometimes the artificial intelligence  will say things that are not true.  What I find  is that hallucinations are  very few. Albums never  get wrong.  Artificial intelligence  reports a bug. It's very likely  that the bug actually exists.  But maybe it's not reachable for some  reason. That's my problem.  It's false positive. I mean, it's the same for  FUSR. With FUSR, you have a lot of results  that are really not exploitable.  So you have to use a few tools.  In a way, you can fix that.  The same with the artificial intelligence. It will report  thousands and thousands of  vulnerabilities that are actually  not exploitable.  But albums never  have hallucinations specifically.  It's almost not a problem  anymore.  What's false positive?  False positive.  This is the main problem because  the artificial intelligence  doesn't know  if some code is exploitable or not.  This doesn't do verification.  It just reports.  So this is basically a job that you have  to do in Microsoft. But it's much easier.  That will get the code.  The other problem is our requirements.  If you don't want to  use a cloud  service like OpenIA,  you need a very big  computer. You need at least  50GB of RAM. This is  a GPU.  To run a model that actually understands  the code. I mean, you can use a Macbook.  You can use  a CPU, but it's  too slow. I mean, you can  see this one function.  It takes about 10 seconds.  If you want to give  a complete kernel,  it will take about a month.  A month using a GPU.  If you use a Macbook,  it will take 6 months, 1 year.  It's actually quite slow.  So you want the  faster IE  possible. And that means that  you need a lot of GPUs.  So, this is about  outdoor applications.  We already know that it actually works.  Not every vulnerability, of course,  will be discovered by this.  Business logic will not be  discovered by this system.  Mainly because LLM  doesn't know about business logic.  Probably if you can teach them,  they can find it. At this stage,  LLM doesn't know about business logic, doesn't know about  budget bugs, but it will find  in the raw flow,  it will find  automatically  all the gigabytes of code.  So, what  is exactly what we did?  We did this part.  This works.  Right now.  But, exploit  is not only that.  We can see that  it's actually the easier part of  exploiting.  You don't require  skills to do what you're doing.  To do vulnerability discovery.  Current models can do it  perfectly, but then you have to  try it a little bit.  It's not an exploit.  It's a confirmation  that the vulnerability actually  exists.  And it's a security.  This is very much harder to do.  You need to explore  the code and create a lot of code  to trigger.  Even harder still is to actually do the exploit  because you have to fight  against protection, against  a cryptographic system,  reliability, etc.  We care a lot about this.  So, basically  this part in the top  is what basically  Google thread 0 and Meta are trying to do.  This one.  They failed, of course.  Because models  are not smart enough.  I'll just try to do this one, and this one works  perfectly.  Basically, the idea is that you  leave this part  to the AI, and  this part  to the AI.  So, eventually,  the artificial intelligence will be able to do  this part here too.  But, there is a problem  here.  It's a dispatch.  I mean, the  artificial intelligence  can find bugs faster.  Dispatching a bug  is much easier.  We can see when you find a vulnerability  you give it to a developer. The developer doesn't  need to be an expert writer. He doesn't need to know  about security. He can patch  the bug very easily.  It actually requires less skills  to find it.  So, if we  make this observation, can we  make a similar  software to  do automatic patching?  Well, we should be able  to do it because it's much easier.  So,  this is a presentation about  an additional software called auto-patching.  Basically, what this does  is very similar to the  auto-hacking, except that  this not only discovers the vulnerability  but also patches it automatically.  The problem is  that sometimes the code generation  doesn't work. So, this has  an additional  step here  to do a closed-loop  confirmation of the patch.  We generate the patch. Everybody  knows that it is very good at writing code.  And Clover is even better.  So, you write, find the vulnerability,  write the patch,  the correction,  and just test it.  If they pass the test, they accept the patch.  And we can do this  massively in every function.  So,  but actually, what happens is we run this  for a month, for example.  Okay, what I did actually with the OpenVCD kernel?  I generated not the complete OpenVCD kernel  but just the IDE before.  I received a stack. It generated  2,000 security checks.  The kernel works perfectly.  This is a rundown of what it cost  me to do it.  It was about  1,000 API requests.  The cost you can see is very cheap.  This is the total cost of  fixing about 2,000.  They're not  security.  Most of them are not  rich.  It's called a  defensive programming.  You check every variable,  every calculation.  Even if it's not reachable,  even if it's impossible to exploit, you check it anyway  because you don't know if in the future  the code will become exploitable.  So basically, we add a lot of checks  to the kernel,  we compile it, and it actually works.  You can see here.  This is the version of OpenVCD  with the other checks.  ...  ...  ...  ...  This is the kernel  with our refactor,  with all the checks added.  It works perfectly like  a regular OpenVCD,  except that  it has additional checks.  This is a lot of vulnerabilities.  It works perfectly.  ...  ...  ...  ...  What else we can do with this?  This is the processor we need.  We have another library here  called Clib.  Clib is a very known library  about compression.  ...  ...  So what we can do is  launch the automatic patch of LCD.  What we do...  ...  We're going to launch  the utility and  we say just patch.  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  ...  This means that actually it can generate a patch and the patch works, because JattyBD  is very good at creating patches.  So it's almost enough to know that it made some mistakes.  Here it made a mistake, so it's a mistake, no problem, it tries to generate a patch again.  It will work, it will work.  And you can leave it running, but let's see what it did.  I'm going to put it and see if this is the function.  You can see that actually this is what JattyBD has.  We have a patch here.  We have a lot of separate paths here.  If you remove this path and replace it for one, that has a new feature.  Actually, in this little time, it did a lot of patches here.  You can see that even the calculation, it did a lot of errors and corrections.  Also, it generates the test.  For example, 64, this is a test.  So I now have a silly library compression with other patches.  We can keep it running.  The interesting thing is that every time you run this, you generate a different set of patches.  So we have a randomization of code.  You can do a custom version of C.  This is impossible to exploit.  The run operation doesn't work anymore because you have a different code every time you run this system.  We are at the end, so we're going to show you one more thing.  What happens if we modify this?  We have, for example, the main code.  Yes, you understand me.  We launch it.  It will actually try to make a new version of C.  With an easier-to-follow code.  You can do whatever.  We can do some examples here.  This is C.Live.  I show it with other security checks.  But we have several other transformations.  We made it obfuscated.  We can obfuscate the code very easily.  You can see it.  Now, transform the code in a version of the code that is obfuscated.  That's impossible to follow.  This code passes all the tests and is 100% compatible with C.Live.  For example, we can tell it to make the code huge.  Ubu, for example.  And now, it doesn't make sense.  You don't understand what it did.  Of course, what it means is different.  But it's very cool.  So, I don't know what this provides.  It actually provides.  I don't know.  So, Ubu, let's create the C.Live.  This library is 100% compatible with C.Live.  I have my own version of C.Live.  And when I send compressed stuff to the conference, I use the Q version of C.Live.  And I also have security checks.  So, this basically doesn't have a lot of offence.  But it's more of a defence.  This is a defence part.  But it will affect the offence also.  So, this automatic patching will certainly affect a lot of the vulnerability research.  So, we're going to see what is the key takeaway from this talk.  Okay.  LLM can actually help to review and discover.  Help is a very, very, very smart word here.  Because basically, they can do it for you.  The problem will be only, you have to sift through all the thousands and thousands of reports.  But it's much easier to look at the code directly.  Now, the problem is that not only can't find bugs, but this will really affect.  It will decrease a massive amount of bugs that will be found.  And also, this is the possibility that you can very easily create your own version of your camera, like I did.  Or your own version of my 3D operating system.  That is almost impossible to exploit.  Of course, not logic-false.  But the memory corruption will be almost, well, not almost removed.  But a very big portion of it will be patched by this technology.  Okay.  But the problem is that it's very likely to be exploitation.  And of course, Meta-Google is incorrect.  Because I don't want to be involved in this kind of work.  Okay.  And if you're interested, you can download these tools.  You can run them on your computer.  If you don't have a big computer in your home, you can use Jativity.  Of course, every bug you find.  Because it's right in the NCA.  So...  But if you patch it, I will actually invest money.  Okay.  Thank you very much.  Thank you.  Thanks again, Alfredo.  So, questions.  Anyone with questions?  Yes.  I appreciate my speech.  I'm going to ask that the test in the loop means  a test to see the vulnerability mitigated  or just test for the code.  The patched code can be built.  Because, you know, to confirm that the vulnerability is mitigated,  the AI should be able to create the kind of low-level POC  to trigger the bug.  Yeah, I'm sorry.  I think I saw the question.  I mean, the AI intelligence build the test and then...  I don't know what.  I didn't get it.  In the loop, there's a test, right?  So, test means find out the bug is mitigated  or the patched code can be built.  Yeah, the test is if the patch can be built.  Most likely, the bug can be mitigated  because the AI understands there is not a bug  but like a possible vulnerability.  It doesn't verify that it actually exists a bug.  It just reserves a variable and says,  okay, this variable is dangerous.  It can possibly...  You can reach this code.  You can exploit it.  So, it generates a patch.  And the current test that I have is basically two.  They have two parts.  One is just built.  It's just compiled.  And the second part runs the test.  Because this patch sometimes can break things.  So, to make sure that it doesn't break additional things,  I run the test if the project has tests.  If the project doesn't have any tests,  like popping BSD,  basically, I have to check the test by hand.  One by one.  Thank you.  Thanks for the speech.  Just to clarify,  for this Chromium bug that was published,  did GPT find the bug first?  Was this, I guess, published  and you tested the code of GPT?  Yes.  I tested it.  This report is actually Lama Tree.  This was written by Lama Tree.  But the one that I showed you just now,  it was just GPT.  You know, there's not a lot of difference between the...  I mean, once the models reach a threshold of intelligence,  I mean, once you understand the code,  it really doesn't make a lot of difference  if you ask Obama Tree or just GPT.  They all generate a report  and they all find the bug.  We can see it in the demonstration.  It was very similar.  I think that the road was very similar.  Of course, you have to be smart enough.  Thanks for the presentation.  Just a quick comment about the fact that  right now you are not able to generate exploits.  It's not possible to generate exploits  because we don't have enough materials  or we didn't train enough  the model to be able to generate the exploit.  Or do you think that  we don't provide enough source code  to the model to be sure that  it understands the concrete path of the...  of the path of the exploit,  where the data comes from  and where you can exploit it.  So, what's your thoughts about that?  The question is why this doesn't...  it can't generate an exploit.  Maybe we gave it more information,  it can't do it.  And I believe, yes, of course,  in only knowing more information,  creating an exploit is sometimes very complex.  It needs heap manipulation,  heap network manipulation.  Sometimes you need to know techniques  that are not known to the other end.  It's like secret mappings  that don't ever change.  So, you really need a level of knowledge  that is not only not public,  but really need a lot of skills.  So, I think eventually  the IE will be able to create some exploits.  I mean, already it's able to create  very basic exploits.  But I think it's not worth  to work towards that problem  because by the time...  because by the time the artificial intelligence  can write an exploit,  a much dumber artificial intelligence  will be patched or exploited.  So, basically you can do it in your lab  because if you find a vulnerability,  it's more likely...  imagine an incredibly smart  charged GPT-10, for example,  it will be able to exploit.  But by that time,  all vulnerabilities will be patched  and charged GPT-9.  I don't... this is basic futurology.  I don't know if this is what exactly will happen.  But it's very likely.  I mean, the patching is very easy  to do in a current...  I mean, a current model  cannot even start writing exploits.  It cannot run and patch everything.  So, I think it's very likely  it will be up in the future.  Thank you very much.  So, do we all have to find a new job now?  Well, that's very interesting  because I can tell you something  that I didn't write in this presentation  is that my job currently, like a blockchain,  is mostly Rust.  So, I say, okay, I save  because this is only what is C, C++  and Rust doesn't have memory corruption.  So, we are working on an audit.  Of course, I cannot tell which one.  So, I... okay, what happens if I use this in Rust?  I mean, the only limitation is the parsing.  I mean, I can't just...  this parser is for C and Rust is different from C.  So, I write a small parser from Rust  and basically feed Rust code.  What happens?  Well, too long, we found...  we found about 10 issues  and this project found 3 or 4 of them.  And in the other one, we found issues in Rust.  We didn't find the critical issues  because the blockchain is more likely  like a business logic and finance  and, of course, we didn't find it.  We did find a lot.  I mean, this is basically generic.  It doesn't have to be C.  It can be Rust, it can be JavaScript.  You can find vulnerabilities in SQL.  I mean, it's like a very...  it's like a semi-senior.  Like, it's not an expert,  also not a junior.  It's quite competent.  So, I have to get a new job, likely.  That's why I started to work on artificial intelligence.  Thank you.  All right.  If not, then thank you again.  Thank you very much.  Our dear speaker.  For his precious time as well.  Thank you.


url: https://www.youtube.com/watch?v=rrll0g5giV0
title: Off-By-One 2024 Day 2 - Win32k Vulnerability Dead Taking win32k Exploitation To The Next Level
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=rrll0g5giV0",
    "title": "Off-By-One 2024 Day 2 - Win32k Vulnerability Dead Taking win32k Exploitation To The Next Level",
    "description": "Abstract\n\nAs a well-known attack surface in Windows system, the Win32k has caused many security problems in history. But with the efforts of Microsoft and security researchers, peoples believe that Win32k has become secure enough that it\u2019s no longer harmful.\n\nEspecially with the continuous updates of the mitigation measures added by Microsoft, vulnerabilities in Win32k have become difficult to exploit, It has caused attackers to lose interest in the Win32k.\n\nIn this topic, we will present the results of our work, which will completely bypass all security mitigation mechanisms and revitalize the ancient attack surface of the Win32k, so we named it \u201cNext Level\u201d.\n\nMore specifically, We will present 5 Win32k vulnerabilities we discovered, which can lead to privilege escalation not only in normal environments. And it can also be used in the sandbox environment, causing the escape of the security sandbox.\n\nAlso, we will introduce the various restrictions Microsoft has imposed on Win32k and how to bypass them.\n\nFinally, we will also summarize whether there is universality in vulnerability exploitation and vulnerability mining methods, and what suggestions we have for future win32k security.\n\nSpeakers\nYanZiShuang is a Windows security researcher at CyberKunlun. His main research areas are Web and OS, Red Team and Penetration Testing.\n\nFollow Yan on X @ YanZiShuang\n\nDeng YunLong is a reseacher specialising in Windows Security, Tor traffic and Deep learning methods. He is currently attached to the information security laboratory at WTU.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 1899,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240901"
  }

  This text was transcribed using whisper model: large-v2

   Okay, hello everyone. Today we are going to talk about the topic of the insertive key vulnerability.  My name is Ethan and my colleague is Yang.  This slide shows the personal profiles of our study category.  Yang is a good researcher in this category,  but I am a speaker to make today's speech.  And we belong to CyberConnect.  That's that.  All right.  Let's kick things off by talking about the history of insertive key.  The insertive key came into play with Windows 24  to boost the web performance of Windows applications and memory usage.  The user interface management and the web-based device interface  were split off from the standard server runtime subsystem.  The CSRSS2 becomes a standalone kernel module.  And the backend Windows NDE 3.5 CSRSS  handles both graphic rendering and user interface management  using fast counter-process communication.  But because Windows demanded heavy graphics,  developers moved to a kernel-based design for recursive protocols.  And the insertive key is made up of three main components.  The graphic device interface, that means GDI,  and the user interface management.  We mentioned both USBR and auxiliary routines,  that means SANS and for the DirectX API.  This was the display driver model in Windows XP 2008.  The window manager takes care of the UI elements like  Windows Display, Screen Output and Input Collection,  and Mass Processing, and many more.  GDI handles graphic rendering, GDI objects,  things like color matching and mathematical libraries,  even the phone support.  In each user session, there is a separate map copy  of the insertive key voices,  which ensures session isolation and security.  Starting with the Windows ListTask service,  we moved to non-interactive sessions.  And user interface privilege isolation  was introduced to stop low-privilege process  from messing with high-integrity processes.  The insertive key rejects multiple callback functions  to interact with the community executive,  and exports the GUI-oriented objects like desktops,  Windows stations, and defined structures,  which provide a GUI sub-system for threads and processes.  We finished the introduction of the insertive key.  Let's look at classical CVE.  It's a classical CVE about the insertive key.  As a typer, you need to carefully define  neural state callback function,  causing the kernel to incorrectly  interpret arbitrary neural state values  as kernel addresses when assessing Windows extended memory.  Thus bypassing normal memory assess checks  and achieving out-of-bounds real-time values.  Now this slide showcases a classical vulnerability  called CVE-2021-1332 in insertive key.  These derivative laws were employed  by the beta-entity group in a disclosed attack.  Locally escalating originally imputed process  to the highest system privilege.  The first function with Windows EX function  in the insertive key full.js module  called the user-mode function.  User 3, 2, then allocate Windows class attributes  via the empty function in user-mode callback function,  which returns the user-defined Windows  extended memory to the kernel.  And a typer can hook the function  and user 3, 2, then allocate Windows class  extra-bias function to manipulate the extra flag  to include the level x 800 attribute.  So we can then call NDDLL callback  return function to return an arbitrary value  to the kernel.  After the callback, the extra flag is cleared  and the unchecked return value is used for  deep memory addressing into a memory access violation.  The figure can be used as a procedure  and won't be repeated.  Next slide.  We will dive into the topic  and explore how to uncover new vulnerabilities  from historical patches.  Okay, in the insertive key driver,  every window is divvied by the tagwind structure,  which includes a function ID field  or we call it fnid.  This field specifies the Windows class  with possible classes,  being in Scrollable, Manual, Desktop, and others.  When a function callback occurs,  the Windows function ID is assigned  a numerical value,  and this permits additional or extra data  to the window from the hook.  More practically,  it allows us to modify the request  of the Windows value  that we write after the output.  The mining lies in the tagwind  to function ID attribute  and the transformation relationship  corresponding to the RTL key  and desktop.  Next slide.  Okay, now we explore the mitigation mechanism  of missing key by Microsoft.  About the mitigation mechanism,  these four methods are usually used  in recipe key related vulnerabilities.  I will briefly describe these four methods.  The first is type isolation.  This is also shown as a CV we need to bypass  in a later presentation.  The first type isolation is implemented  through several interconnected structures.  The four primary data structures  involved in this mitigation  are C-type isolation, C-section entry,  C-section bitmap allocator,  and the RTL bitmap.  The type isolation mitigation  is introduced in the research2k command  of Windows 10 version 17.9.  Changes how GDI bitmap objects  are located in the kernel space.  Specifically, the surface header  is located in a section view,  where the piece of data buffer  is placed in the page4 section view.  This change effectively prevents  the kernel exploitation technique  of using bitmaps as targets  for limiting memory corruption.  It's no longer possible to create  an alliance tree of adjacent bitmaps  where the end of one piece of data buffer  directly follows the header of the next surface object.  If you want more information,  you can visit the ParseLabs website  where it's explained in the video.  The next, KD-SLR,  means Kernel Address Based Layout Optimization.  Also, it acts as a kernel-based application  to make combo flow checking and task harder  by remapping the base address of the kernel on boot.  By remapping the base address,  we can no longer hard-code values  to jump into the kernel.  Just like R-Space, KD-SLR,  we need some form of link  to know where to jump to next.  That's the way we produce  the kernel control flowchart.  KCFG is a highly optimized  transform security feature  that was created to combat  memory corruption vulnerabilities  by placing time registration  on where an application can execute the code from.  It makes it much harder for exploits  to execute the arbitrary code through vulnerabilities  such as buffer overflows.  Kernel Data Execution Prevention  is a system-level memory protection feature  that is built into the operating system  starting with Windows SP  and Windows Server 2003.  DEP enables the system  to mark one or more pages of memory  as non-insertable.  Mark memory regions as non-insertable  means that the code can't be run  from that region of memory,  which makes it harder for the exploitation  of buffer overflows.  Let's finish the presentation.  We will cover five CVEs  related to M32T.  There are the CVEs we will discuss today.  Next, I will provide a brief analysis  of each CVE.  The first CVE,  2021-41357,  is a vulnerability based on  a twin-structure UVFM.  Because of the lambda function,  I have checked the reference count  and the free template directly  and processed the UVF.  The second CVE,  2023-2274,  and its vulnerability's predictability  is to use multiplexed CVE callback  to reduce if-view-windows, etc.  and truncated-function segregation  and callback to R3.  The last three vulnerabilities  which are mainly about patch bypass  and vulnerabilities caused by  segmented addressing through FNID  and RTLP sending extra address.  Okay.  Let's introduce the first CVE,  2021-41357,  and about the CVE,  the following exploit,  Sagger, is a type-association bypass.  When the first function,  M32T,  through this function,  M32T for window.js  callback to R3,  using the function  locate-window-class-appropriate-function  and set the allocated  extended-window-and-read-address  to 0.  It triggers a lambda function  on a failed application.  This lambda function first uses  thread-unlocked-one-deprecise  to return the window's primary address.  After some  read-pull operations and  deferencing,  this function directly  returns the object function  to possibly delete the window.  If there are other references  to the window at that time,  the process will immediately crash  at the end.  There are many ways to exploit this function.  For example,  by setting up the callback  to the R3 function  for parallel window  in the  silent-allocated-window-class-appropriate-function.  This function  will clean up  the child window  using VFD.  The parent window  can have many child windows.  There are alternatives  for the end of the main window handle.  If we want to modify  the parent window of the child window,  we can modify the initial  parent window reference class.  After the parent window is released,  the exploited many windows  are created to override  the kernel address  of the initial parent window,  and at which point  the memory of the initial parent window  has been overrided by other windows.  Calling the function console.control  and creating a small RTL kit  to do the desktop login function.  Since there is an extended window handle,  the function console.control  will call back to R3  using the exec3-windows-class-appropriate-function.  Here we can hijack the stash  by using a hook  and modify the parent window  of the child window  using the reference count  and then call the exploit window  to be cleared.  This will cause a UEF  because the reference count  becomes asymmetric.  After the cleanup is completed,  due to type oscillation,  we can't do tool injection  to occupy the space  of the screen type window structure.  Therefore,  we can only create  a large number of type window structures  again to occupy the  initial type window structure  and set the extended window memory  to a very large value  to end the function.  After the function clears,  we can modify the device  of the PIST desktop pointer  in the type window structure  that holds the extended memory  and the type bit.  This has already been changed  to some other window  such as the auto-bounce real-time  for PIST desktop A  by passing the type oscillation  to the callback function  and the special addressing method  of RKR A.  This allows us to achieve  kernel pool of auto-bounce  with invite  and convert it to arbitrary address  with invite.  This video shows the  exploit in Windows 10 H2.  You can compare it.  It works well in Windows.  The video comes back backwards.  That's CVE-2003-28274.  This exploit process is  used in Windows.  You can compare the process  to RTLB, auto-bounce real-time invite,  automation, type oscillation.  Then let's dive into it.  First is to create a window.  Adjust the check TLS structure  with extended window memory  using PIST window.  Then adjust it as a DDE server  in the subsequent code  and call console control  to set the flag base  for the window memory  allowing it to be managed  as a RTL heap.  And then in the function  with windows,  after the RTL base releases the memory,  it sets the memory location  and draws the offset of R3 heap to 0  indicating that the memory has been released.  Later in the function execution flow,  the function KLDB function  provides an opportunity for the R3 callback.  The specific code snippet  deals with dynamic data exchanging,  which is a form of inter-process communication in Windows.  The code snippet handles the DDE message  in a Windows application.  It creates and deletes global patterns  that handle DDE initial and device message  and sends the deployment message  back to the initialing or advising window  and destroys the window  upon receiving a DDE device message.  This code handles the DDE message  in a Windows application.  It focuses on assessing the DDE management message.  It allocates and loads global memory  for a DDE device structure,  sets various fails in the DDE device structure  to configure the DDE device options,  adds a string to the global pattern table  and sends the DDE device message  to the Windows testing site Wpera.  Handles memory cleanup  if sending this message fails for other messages  in a default Windows procedure.  And then by coping the DDE callback,  we get a single shot at rescuing the population.  We immediately trigger the vulnerability  by calling the function of non-PTR.  However, instead of the rest of the standard  extra address, non-start and offset  is addressed by RTL-HEAP.  Since the offset is 0,  it doesn't affect the function.  We then provide access to the data structure  stored in RTL-HEAP.  Start retrieving,  and all our runs will arrive  in the kernel's RTL-HEAP.  And last, we introduce a CVE  that our team uses in CTF computation  named the TenFootCalc.  It's a bypass of CVE-2021-1732  type call function vulnerability  in the VSWP framework.  And the tagger can make kernel calls  by calling relevant QI APIs in the node,  such as the function Windows Probe,  switch Windows Probe,  and two-tip Windows Probe.  This kernel function triggers a callback.  The tagger can interpret this callback  by cooking a function named  allocateWindowClassAdvice in kernel.  And they use the  NTUserConsoleControl method  to set the console window flag  of the tagging key object,  thereby modifying the Linux tag.  After the callback,  the system doesn't check if the window tag  has changed due to the tag computation.  In reference to incorrect data,  the differences between before and after  flag computation is that  before setting the flag,  the system deletes the tagging key  for the key attribute of the  related node pointer.  After setting the flag,  the system deletes the tagging key  for the key attribute.  We then offset the kernel.  That call is reached by the tagger  control and then used to  all of our suite advices.  This is a brief analysis,  and the most  specific information is this.  First is the link  that the function callback  and the insert new key  can be called in a  custom callback function  to set the related node to mode 1  with the passive argument set as bold.  The first argument 1  does not exist,  and argument 2 must point to the buffer  because the first two words  must be valid when it's handled,  and argument 3 must not be  there when executed.  The next object  calling NTU callback return  enables the return to the kernel  for the offset of XLP  with the window table  assigned to a PS drive  based on these two  and the side window line  Tagged key structure  of the window table can be modified  and then we need to get the offset  to the desktop heap.  The crucial point  to understand really well  is that the CS progress value  of the window table must be smaller  than the offset  to the desktop heap  value of windows  and 1 and 2  start with the  restriction of a small  with extra  parameter of pins level  bypassed. A large value  can be written to the structure of  the Tagged key of windows 1  and its true bypassing  parameter of the  side window slot function  where window level is called.  And the  CPE 2022  66914 and the series  pinpoint is based on the function  pin switch window.  The vulnerability  requires booking the  processor to call back table  on either the key  specifically this function.  And the vulnerability  calls the switch  window code to invoke  the validate class  and the size. The first  time switch window code  is called, it passes the  WM3 message before  accessing its module.  It calls validate class  and size function.  At this point, the window  doesn't have an ID  size. The assignment  of an ID occurs  at the end of the function  class and size. So  it enters the function logic  or locates the user mode part  of the extra bytes for the window.  However, by this time  the machine has already initialized  and set the  kernel mode part of the window extra bytes.  And the  nest has also been reassigned  in this logic  to call to the function  extra bytes  where we have triggered the user mode  through the vulnerability attack.  The function stores the  extended memory in the FID  in non-set and  in less than several extra bytes  the content is stored  in the server extra bytes.  Now it modifies the  kernel pointer text which we  named for stored in the  server extra bytes in the  user mode callback  of  and  the method is to call  setLimitBDRAsync  to callback to change the pointer  state in the kernel to an arbitrary  user byte class.  Next,  to achieve this relation,  the function here  switchViews  is to be called by  sendUserMessageNumber  efs1  according to the switchView  which will perform memory operations  on the datastore in the  text switch dimension 4.  Since the memory  is controllable at this point,  I will show you a graph  which is created  and related to the arbitrary  address that we call it as  modifyMemoryPoint  and offsetBit  offsetLimitBDRAsync  in the text switch dimension 4 pointer  is stored as the  server extra address  lastBit  and the last term, CVE  let's talk about the CVE  202.4.1.1.3  and  the key function  about this CVE is put on the top of the  slide  and triggering  the vulnerability requires opening  the process internal  kernel callback table  and  this function  in the  inVisibility, this callback  triggers the function  class and size inVisibility  to trigger  the class and size function  the vulnerability calls  the  sbWin()  on the first call to  the WAN  message is passed  and  in this logic, I showed you  the call to windows  class s4bys will trigger the  user motorbook through a vulnerability attack  and this book will call  the WF-dialog pointer  which will change the window  FID to FID-dialog  and add the  WF-dialog-wint  the windows flag  because the window is set with  the WF-dialog-wint flag  that window non-CVR  will interpret the windows as a  dialog box  allowing the code to replace the first field  with a controllable value  and this also makes it possible  to leak the kernel address of the  TechWin structure and  achieve information disclosure  Let's make a brief summary  Mr. Duque has been  a critical commenter of the  Windows operating system  since 1994  and I admire the efficient  graphic performance and  user interface management  except it's impossible  to ignore its importance  and it has also been  a frequent target for vulnerabilities  so it's always  the hot sauce of vulnerabilities  and the methods for  discovering vulnerabilities are generally  more universal  and techniques such as following  tests, static or dynamic  analysis, symbolic  explanation and so on  one more vulnerability can be shown  on the ground  so I'm open  my speech is over  thank you  applause  we give  another round of applause because this is  actually one of the first time he's presenting in public  so some encouragement  thank you  applause  any questions from the  floor?  alright  this vulnerability  can be used to escape sandbox  from browser  actually  it can cross the  sandbox  in many environments  even  currently in 2034  can you repeat again?  currently  can  Win32k be  exploited in the sandbox?  I need you to check it  I need you to check it  it may work there  can you check it  after the conference?  thank you  thank you  were these bugs  that you found mostly found via  static analysis  or fuzzing  how do you see  the future of Win32k bugs?  the future of Win32k?  yes  I recently read some  academic papers  in user needs security  one more funny truth  about the Windows kernel  even the other platforms  such as Linux, Android  I think this way  is more frequent  to use in this  Windows kernel  because the Microsoft  application  has its limits  so I think this method  even the  artificial intelligence  method can affect  the Win32k  Win32k modules  to find more vulnerabilities  or to protect  or attack  it's all ok  thank you  that's all your questions  thank you  alright  if not then  one final applause for Yit Long  thank you so much


url: https://www.youtube.com/watch?v=2reOuSSDavM
title: Off-By-One 2024 Day 2 - The Forgotten Treasure In Classic Targets : Hua Hangyu & Wu JunTao
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=2reOuSSDavM",
    "title": "Off-By-One 2024 Day 2 - The Forgotten Treasure In Classic Targets : Hua Hangyu & Wu JunTao",
    "description": "Abstract\n\nAs is well known, there are numerous mature fuzz testing tools on the market, including iconic ones like AFLplusplus for general objects, syzkaller for Linux kernel.\n\nHowever, despite the continuous and round-the-clock efforts of these powerful fuzzers to test these targets, several longstanding vulnerabilities have exposed in recent years, posing significant risks for privilege escalation.\n\nThis suggests that many secrets still lie deep within the code, beyond the reach of fuzzing techniques.\n\nTherefore, by investigating the pain points of fuzzers and conducting manual code audits targeted at high-value objectives such as the Linux kernel and mobile RCE-involved decoders, we have successfully uncovered dozens of high-value vulnerabilities.\n\nThese vulnerabilities, which are not easily detected by existing fuzzers, may enable privilege escalation to obtain root access. Through analysis of these vulnerabilities, we have devised methods to enhance fuzzers and discovered multiple new 0days.\n\nSpeakers\nHangyu Hua (@HBh25Y) is a security researcher at numen cyber and the co-founder of Shuffle Team, mainly focusing on low-level security such as boot chains, kernels, etc.\n\nJuntao Wu (@Dawuge3) is a security researcher and the founder of Shuffle Team, mainly focusing on mobile/web3 vulnerability discovery and exploitation. He was inducted into the Samsung Mobile Security Hall of Fame 2021/2022/2023.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2293,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240901"
  }

  This text was transcribed using whisper model: large-v2

   So, good afternoon everyone, welcome to our talk.  Thank you everyone for sticking to the last, second topic.  And this is about some benefit research in classical techniques.  So, a little about us.  My name is Junhao Wu.  You can just call me Dawu He.  I'm a security researcher at CERTIC.  And I have founded the CERTICO team, which likes to explore new things.  I have been selected into sensing and hardware owner of mobile security hardware green screen clients.  At the same time, I have submitted some benefits to Google and other beneficiaries.  Now I'm mainly focused on mobile and web 3.  And this is my partner, Tang Yihua.  And he is a security researcher at Yunnan Cyber.  And he is also the founder of the Shuffle Team.  He mainly focuses on the low-level security research.  So here is the agenda.  The content mainly revolves around the forgotten trash,  focusing on the vulnerabilities that are often overlooked by security agents  and can not easily be detected by tools.  And I have divided the content into three parts.  So let's take a first look at why forgotten trashes appear.  Here is a little background.  So we once had a doubt.  Is this one of the reasons why the exploit chain continues to appear?  If you are familiar with the news about web 3 security manipulatives,  you should know that if there are problems in the project,  it is very easy to cause direct economic losses.  Therefore, the audit habit of web 3 project  is to find all the vulnerabilities as much as possible.  However, the differences between the web 2 project and the web 3 project  is that its size is very large.  And it is almost impossible to guarantee that all vulnerabilities are discovered.  Therefore, some have been tested by tools, of course,  that have been manually audited many times are often ignored.  This is the first vulnerability since a while that I want to talk about.  It is very special because many security researchers have noticed and retweeted it.  The reason for this appears in 3 types that have been tested and audited many times.  And because there are many projects using 3 types,  so it has a very wild impact.  The vulnerability exists in the lowest-biased PNG,  and which could process the PNG images embedded in fonts.  This function first will obtain the image width and height from the head  as 32-byte integrals,  and then it truncates the opt-in values to 16 bytes  and stores them in the T-squared measure structure.  Then it will use the truncated values to calculate the bit-byte size.  Then it will block the back-end stores of that size.  You can see it finally passed the PNG structure and the back-end store to the PNG function.  So normally this isn't a vulnerability that is difficult to find,  but why didn't the father find it at that time?  From the fuzzing test results,  you can see that the black box fuzz tools  and the fuzzers corresponding to the OASIS fuzz platform  were used to test this code representation.  But the bugged file isn't being fuzzed at all.  So it is a very clear gap.  And the next, let's turn our attention back to the recent vulnerability.  This vulnerability appears in the relevant parsing code of WebP.  It occurred in September last year.  It is also the vulnerability in the wild,  affecting the security of Android, Chrome, macOS, and other platforms.  The cause of this vulnerability is the problem of the auto-bounce writing  in the invention of the Kafka encoding algorithm.  In the processing flow,  the decoder first reads the prefixed encoded data from the image data stream  and builds a completed Huffman encoding table based on this data.  Then the decoder decodes the compressed data in the data stream  according to the table and restores the original image.  According to the standard Huffman coding algorithm,  when constructing the Huffman coding table,  the first level table will be used.  This table is used to carry Huffman code with a length less than 10 bytes.  The default byte is 8 bytes.  If the length exceeds 10 bytes in coding,  the decoder will allocate a secondary table to carry this part of the long encoding.  The problem is that the Huffman coding table saved in the decoder's default picture is reasonable.  So it calculates the maximum memory length in advance based on this assumption.  The core premise here is that the encoded data must confer  the specific of parametric Huffman coding.  That is, the Huffman tree should be a complete binary tree  with each left node corresponding to a prefixed code.  There are no unused left nodes.  However, since the Huffman coding table data comes from the on-chess itself  and may be irreparably congested by attack,  the decoder passes a completed binary tree  without checking the valid date of this data  and may allocate too much of the secondary table  and will cause the total memory usage to exceed the pre-allocated size  and a deep backflow will occur.  Regarding the key point of this availability,  we can actually focus on two main lines.  The first is the counter area and the second is the root table.  Here is the counter area which stores the numbers of the users of each line of the code.  Specifically, the code line is allocated space in the top-level function with Huffman codes  and obtains the corresponding specific data in Huffman code lines.  This root table is actually a Huffman table  and its boundaries are determined at the beginning.  The most important thing here is the table size  can have user, control, color, cache size variables  to affect the selection of the fixed values.  The Huffman tables are logged in using the number of each tree groups  times the table size times the size of Huffman tables as the final size,  most of which cannot be changed by the adapter.  The patch here is actually the in-app version.  In fact, the repair method adopted by Google  is to add some new structures for preparation and verification.  But the repair on iOS is closer to the original version.  It can be seen that the most direct fix here is to check  whether the access element has crossed the boundary.  If so, it will fail on the original panel.  However, this fix may not be particularly perfect  so they later adopted a more complex fix patch.  And since WebP is also a project in Google OSS fast platform,  let's take a look at why this variability was discovered by researchers.  We can see that the function file where the problem occurs  has actually been relatively fully tested by photo coverage.  Each function has been 100% covered.  So where does the problem lie?  Here we need to reflect why hadn't this bug been found earlier?  Why had the library not been found enough?  Had it not been found right?  In fact, the deep-seated reasons why this variability  hadn't been discovered are as follows.  First, its travel conditions are very complex.  It needs to overflow data of sufficient length to track a crash.  But in the actual environment,  the space allotted by the malloc is usually larger  than the actual parameter size passed in.  Secondly, the tracking of this variability  also requires the cooperation of the first-level table  and the specificity of the encoding data.  That's caused a lot of bugs during the blockchain version.  And this is the last variability.  This variability is located in the TCP-ULP model.  There are some protocols in the Linux kernel that support this model.  And these protocols that support this model need to  implant TCP-ULP-AUX structure,  which contains a clone function point.  When the TCP three-way handshake protocol is complete,  that is, when the TCP listener states  change to TCP established,  SK clone lock will be called to generate a new SK.  When the protocol is used, such as subflow,  and implements the clone function,  the clone function will be called to process the context state.  If there is no original SK,  it will copy its own context to the new SK.  For example, the TLS protocol doesn't implant this clone.  This will result in two different SKs  pointing to the same context,  which is a typical double-free problem.  The interesting point of this vulnerability  is that the TLS protocol only allows  the TCP established step to be set  after the three-way handshake is successful.  So we need to use the same software to repeatedly  perform the three-way handshake to check this vulnerability,  which obviously violates the general password coverage standard.  Next, let's turn our attention to the second part,  review the targets.  We can see that since Google offered a bounty for Linux,  a large number of exploitable vulnerabilities in Linux core has appeared.  And Hongjiong also has Ubuntu LTE project every year.  So Linux seems to be a great target for BAU.  As we all know, the most common solution for bug hunting is farming.  So we want to fast Linux.  First of all, the tech service.  A year or two ago, EPF was very famous  and had many vulnerabilities.  But due to Ubuntu's setting,  the user couldn't access this module.  You can see the screenshot on my computer here.  Next is IOUMI.  Last year's EPF had,  it clearly showed that IOUMI had many vulnerabilities  and most of them are exploitable.  These vulnerabilities could even be used in Android critical before.  But recently, Android disabled unregulated users for accessing IOUMI.  However, many distributions like Ubuntu know its use.  Therefore, it's a good tech service  with repeat code updates.  However, the disadvantages are also perverse.  Too many people have deleted,  which makes the vulnerabilities easy to repeat.  Then there is our superstar, Netfilter.  We can see that a large number of vulnerabilities in Google KCTF come from this module.  We can even see that most of them.  Looking back at the vulnerabilities in recent years,  this module has always been a hotspot for bug hunting.  This fully provides that this module is complete enough  and may contain a lot of treasures.  Moreover, a large number of well-known security researchers  have published their own treasure-hunting articles for this module,  which makes it very easy for us to get stuck.  But the price is that this makes the vulnerabilities you find in Netfilter  will be easy to repeat even higher than the IOURI.  By the way, as a large number of Linux kernel vulnerabilities are discovered,  the price of Ubuntu on Tobio is decreasing year by year.  So, what is the target of funding?  After some research, after some searching,  I finally decided to fund in the network package scheduler.  Its advantages are that it is complete and has no vulnerabilities requirement,  and most importantly, it has less attention.  Its disadvantages are also perverse.  It has poor generalizability and requires a new network space.  So, how to use NetScheduler?  First, we need to create an SD, then call sendMessage with ASConnect link.  There are also a lot of RTMs for us to choose.  You can choose to create a new QDisk, a new class, a new chain, a new filter, and a new action.  RTM New QDisk has many options,  like Schedule FIFO, which means first-in-first-out,  and Schedule HDB, Schedule Multicube.  RTM NetFilters also has many options.  But first, we need to select which CLS you want,  like CLS.UserDistribute, CLS.Follow, CLS.Flowers, and CLS.EM,  like EM.Text, EM.IDT, EM.UserDistribute.  RTM New Action is the same.  You can choose the actions you want.  So, after kind of finding these structures,  it's easy for us to start planning,  like you can use this code.  Unfortunately, after a while, we didn't have any good results.  So, I decided to do a code review directly.  Then I found something interesting.  Let's look at the CLS.Flowers.  We can see that the FLC,  we can see that the FLC,  this general OPT has an LOS infrastructure  that directly uses the LOS parameter,  which looks like a potential variable for the ability.  The LOS of this LOS is 255.  But when we continue to look at it,  our subsequent code actually checks the length of length.  So, this isn't a bug.  My spider science told me  I should go back and take another look.  Let's go back and take a look.  We can see that after getting OPT from the LOS,  OPT is assigned a value immediately.  And below the arrow is the length.  This length will be 0 when we first call this function.  And R1, R2, R3 are also 0.  So, it looks like 0 is 1.  The arrow contacts the OPT struct and the data.  Length points to the end of the data filled in the arrow.  It's not difficult to concentrate a suitable length.  And then OPT overrides length to 0.  Now we can bypass the check for length  and fill the subsequent data into the structure  to complete the autofound right in the structure.  The limitation is that we can only overwrite over 128 bytes.  If we look for this structure in the source code,  we can see that the structure where our arrow is located  is actually imbibed in two different structures.  One of which happens to have a chain that can be overwritten later.  Which means that we can modify a head point  which can easily convert this vulnerability.  The other contains a function point,  which means we can modify and delete a function point.  Since the CLS flower provides us with the function of passing the data,  we pass the bank to the user space.  It may depend on the OPT of each handler  and the total length.  If we continue to fill data in this arrow after checking the structure overflow,  since our length has been modified,  we will start writing the content of the data again.  After layout, we can modify the length of part of the original OPT.  At the same time, build a fake OPT struct at the end of the arrow.  Since the kernel will be mistaken,  since there will be more data passed in later.  Realizing the autofound right in the structure  we can link the function point mentioned earlier.  That's the exploded Ubuntu.  More details can be found in the link below.  Now let's turn our attention to mobile RCE  and the parsing logic of HEAP.  HEAP files are special cases of ISO-based media file formats.  Latest conditions and timed media and metadata streams forms a check,  whereas static media and metadata is stored as items.  Consequently, HEAP has the following basic designers.  First is, still images are stored as items.  Second, image sequences are stored as checks.  So a file may contain both image items and image sequences,  checks along with other media.  The picture on the right illustrates how a file player processes a coded image  and the derived image includes a file.  The file player decodes a coded image into a reconstructed image.  Similarly, the file player applies the operation of the derived image  to the indicated one or more important image  to obtain the respective code image.  The flowchart here simply shows the parsing process of simple on-sensing.  Since the HEAP I mentioned before  can actually be regarded as a combined type of file.  This is mainly divided into two parts.  The first part is about the HEAP file HEAP parsing,  and the other part is about the parsing of the file content inside HEAP.  Since the file content is highly inclusive,  its content will lead to parsing of some other file formats.  At that time, tools like AFL++ hadn't yet introduced filing tests  that could be directly run on mobile phones.  So I initially wondered why I can't test these function libraries through the QMU.  But this idea was quickly rejected because  the gen-line interface elements of these function libraries  are relatively complex Java objects,  which may not be well suitable for the simulation testing QMU.  So I considered whether I could use Vreda to write a fuzzer  for completely code coverage calculation.  So here it is, a not-too-bad fuzzer.  Its main improvement is that it doesn't both mutiline functions through JS,  but directly use the function interface brought by the Vreda core.  In fact, the Vreda core itself is the underlying hooking framework  directed through the QMU object,  so we can directly use its underlying interface.  The function shown in the pictures here,  the onMessage() will transmit the code block information  checked by the underlying stacker back to our Honey's program,  and thereby realizing the collection of block coverage  and some other functions will support some crash or excess signups.  So the final effect is that I can run my fuzzer directly on my phone.  The result of fuzzing test is a total of 16 manipulations were discovered within mouse,  including 5 critical and 1 high.  The CVE-2021-39804 is actually a bit interesting.  This manipulator itself is not very dangerous,  but it does bring me some inspiration and encouragement,  which proves platforms like OASIS Fuzz cannot achieve 100% success,  even if faced with some fuzzing modules that have been tested many times.  Different fuzzing methods will still be able to discover different security manipulations.  So let's compare some existing fuzzing test flow methods,  which are basically connected from the last year, Zerocon 2023.  So MJ, he wrote a great series of blogs,  he had a research about closed-source and binary fuzzing,  and I used to write the 3D fuzzer.  The folks have a topic about Android J9 fuzzing,  and the guys from Zhejiang University also test on something called closed-source libraries.  So fuzzing testing can be a general approach to find bugs in closed-source native libraries.  For mobile testing targets, code coverage should be the most effective fuzzing testing method.  From an object point of view, currently in Android native library,  basically all the function libraries' objects can be fuzzed tested.  For shared libraries, if the parameters are memory, address, or object,  string, file, or descript, we can use QMU to collect the code coverage.  If the parameters are objects of Java library,  we can use JVM or QMU or Frida to collect the code coverage,  such as a survice process.  And there is already a corresponding tool, like Chatsify.  And its implementation is also to collect the code coverage through Frida.  And for native network process and session,  Netella from Google Project Zero did a corresponding buzzing test  on some mainstream information-transmitting software,  including WhatsApp and other applications.  So the method used was also similar to the Frida passive fuzzing test.  So in theory, it can also use Frida to collect the code coverage.  So is there anything else we should pay attention to?  As we mentioned before, the CVE-2020-15999 is missed by fuzzing test operations.  And the CVE-2020-4863, they are missed because of complex conditionals  and deep travel paths.  Another point is that the seed source of fuzzing test always affects some aspects.  Sometimes it is difficult for us to find a seed file that can trigger deep-level code very acutely.  So in addition, fuzzing testing tools themselves usually have various problems.  For example, Frida is very unstable and prone to crash in the actual user's theory times.  And its testing speed is very slow.  And due to the particular of mobile Frida code coverage crashing,  the multi-line process parallel fuzzing test method is also very difficult to implement.  So it's time to review.  And here is the CVE-2020-30699.  In fact, this isn't a very complex type of limiting.  It still happens in the header fuzzing module that appears in the GIF file.  So why hasn't this bug been found by Frida?  So here is the details about CVE-2020-30699.  And the V38 variable will store the file data read from the GIF.  And it will use the size in the subsequent read function.  And V21 points to a memory variable.  And its header stores the value of 1.  And it will pass 1 from the V21 as the memory read area.  So since we can control this total length,  it seems an out-of-bounds override.  But there is a limitation.  The sum of the lengths is actually the same as the elements  accumulated in the MyLogElement object before.  So this will have to be no problem.  Actually, the real problem is here.  There is an integral truncation vulnerability  which can cause MyLogElement to allocate less space than expected.  You can see that in the example,  this vulnerability uses the AND instruction instead of the MOV instruction.  So if our logic is as shown in here,  it will traverse the collection area in the HVCC function.  And then it will traverse the NeoUnit inside each area  and calculate the final space size that needs to be collocated  based on the size of each NeoUnit plus the length of the prefix.  Therefore, due to the previous integral truncation vulnerability,  an out-of-bounds right problem will occur here.  So why is this vulnerability not defined by father?  It is the vulnerability that also requires mutiline connection to match.  This parsing part is a sub-model in the head.  And it requires that the key file has mutiline NEOs.  But in fact, the value of each NEO is limited in the small size.  And finally, the sum of these values must exist  the maximum value of AND 32.  Next, let's turn our attention to the content of this report  and enhance our fathers.  So, why father fail?  The first kind is that the more use of this vulnerability is difficult to construct.  For example, some memory destructive vulnerabilities  may not have induced effects such as crashes  so when they write out-of-bounds,  they may perform it at the internal of some memory unit  and the modified value is reasonable under certain probability.  The second situation is usually more common  in some process files parsing.  Because in some cases,  the character parts of the code are many and complex,  it is difficult to determine all the key process modules in a short time.  Therefore, in most cases,  more attention may be paid to the earlier processing modules.  There is also the third type of vulnerability  which is often the hardest one to find.  It needs to be checked when the mutiline conditions are met at the same time.  In many cases, we may not actually understand the key points  involved in parsing a function.  At the same time it is closed,  so in closed parsing tests,  we usually focus more on the adaption of earlier interface elements  with the improvement of the code coverage.  In attention, there are still some types of vulnerabilities  that are difficult to find with parsing tests.  So we improve our parsing in the following ways.  First, for mutiline layer nest structures,  we pay more attention to the efficiency of the parsing testing  to reach specific blocks or instructions  rather than the code coverage.  This means we may pay more attention to the deeps of the code testing  rather just than the breadth.  Because many existing parsing test tools focus on the breadth,  but some test results or vulnerabilities  only occur in the shadow code.  Frequently crashes in the shadow logic  are not very competitive to test the deep code.  Secondly, we pay more attention to the path testing  of some key interesting locations.  For example, we use mutiline test on the same path,  but we use the different or unique value space.  In general, this is the guided path testing structure  that focuses more on some forgotten vulnerabilities.  And here are some new vulnerabilities tests we discovered.  We can still find some new vulnerabilities on these targets.  However, since some vulnerabilities are still being fixed,  we will mainly talk about the latest canal here.  Hi.  So the bug is in the schedule module.  In the module, we need to delete the code  and make a new variable with a new Qtist.  The length of the tree is determined by the number of CX queens.  We can see that at position 1, QOPT bands are assigned.  At position 2, the node is allocated by Qmax binds minus Qbinds.  At position 3, Qbinds is assigned by Qoptbinds.  At position 4, we put some extra Qtist objects into the removed analog.  And then freeze them at position 5.  Why is the old Qbinds used to allocate the removed size at position 2,  but the new Qbinds is used in the for loop later?  This seems strange.  If maxbinds minus newbinds is greater than twice maxbinds minus oldbinds,  the for loop may write Qoptbinds to a tap point.  That will be freezed soon.  But first, we need to figure out what number CX queens and real number CX queens are.  After I checked the source code of AI and tried it in my old network card,  I found that these two require hardware support.  So this is a useless part.  My spine size tells me these are not that simple.  What if we create a virtual network card?  Boom!  We can now control the real number CX queens and default number CX queens to 128.  Here is an example.  First, we create a network card.  Then we set real number CX queens to 124,  and call maxmultiple twins again,  which will create a 124-valued object.  Then modify real number CX queens to 190,  and call maxloop twins again.  We can write a tap point or loop that will be released immediately.  Vulnerability was fixed by us a few weeks ago.  Here is a demo.  Thank you.  Thank you.  Thank you.


url: https://www.youtube.com/watch?v=u_2sRheRYkQ
title: Off-By-One 2024 Day 2 - Make N Day Great Again..
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=u_2sRheRYkQ",
    "title": "Off-By-One 2024 Day 2 -  Make N Day Great Again..",
    "description": "Make N-Day Great Again - The Story of N-Day Full Chain from browser in guest to SYSTEM in host\n\nAbstract\n\nDuring the last year, numerous vulnerabilities were patched, and some of them were proven to be exploitable, as they were exploited in the wild, Pwn2Own, and so on.\n\nWe have continuously tracked these issues and written the Proof-of-Concepts and exploits to keep them in our vulnerability database.\n\nAlthough each vulnerability itself has a critical impact, we think it would become more powerful if they are chained into a full chain exploit.\n\nTherefore, we wrote an exploit chaining several vulnerabilities chosen from our database and demonstrated the exploit on X; the exploit starts from a Chrome browser running in a VMware guest and then manages to achieve SYSTEM privileges in a Windows host.\n\nThis scenario mimics a situation where a security analyst clicks a malicious link in a virtual machine. The N-Day full chain includes six unique vulnerabilities; three of them were exploited in the wild, two of them were used in Pwn2Own 2023, and the last one, a variant of a Pwn2Own 2023 vulnerability, was found by one of our team members.\n\nIn this presentation, we will explain the root causes and the exploit techniques of each vulnerability and how we connected them into a full chain exploit.\n\nWe will also discuss chaining details to glue our exploit pieces together successfully, including how to bypass V8 pointer compression, implant browser sandbox escape vulnerability in JavaScript code, escape the browser sandbox with the pickup window, and drop the exploit binary on the host of VMware.\n\nThis presentation will cover overall concepts from browser to virtualization and OS, and you will have a comprehensive understanding of them after this talk.\n\nSpeakers\nJeongOh Kyea is a researcher at Theori Korea and has an interest in automatic vulnerability detection, binary analysis, and exploit techniques. He received a BS and MS degree in KAIST. He was selected as the Most Valuable Researcher(MVR) in 2020, 2021, 2022 from Microsoft.\n\nGwangun Jung is a security researcher at Theori. His main research areas are operating systems, virtualization, red teaming. He is the Pwn2own Vancouver 2024 Virtualization category winner targeting VMware Workstation and received CVEs from Linux/VMware/etc.\n\nFollow Gwangun on X @pr0ln.\n\nYeonghun Kim is a security researcher working at Theori. His main research areas are web browsers and JavaScript engines, especially Chrome and V8.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2121,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240901"
  }

  This text was transcribed using whisper model: large-v2

   Good afternoon. Welcome to my presentation.  This is the last session of O5-1 conference.  My topic is about the story of creating NDAful chain.  First, let us introduce ourselves.  My name is Jungwoo Gae, and I collaborated this project with Kwanghoon Jung and Younghoon Kim.  We are the vulnerability research team of Deory.  Before I start our story, I will first show you the NDAful chain we have created.  I think some of you may have already seen it, because this video is also posted in our company's SNS.  We started the vendor in the guest.  Finally, we got the system shell in the host.  This is our NDAful chain.  Now, let me tell you about the story.  This is the content of this presentation.  To tell why we started this research, I can't leave the fairing service, our threat intelligence service.  This service is the vulnerability report database since 2019.  Until now, 486 reports exist and half of them has working exploits.  You can check the information of the fairing service in our company's blog.  This is the simple statistics for the reports in 2023.  71 reports were written and 37 reports have own working exploits.  Also, some of these reports have been proven to be exploitable because they are used for in the wild or exploit competition like hunter-hunter.  There are tons of reports on Fermion, so we thought that we can do something interesting with them.  Also, we wanted to get some advertising for Fermion service.  Here are the ingredients for a delicious exploit.  First, we thought about the fruit chain.  This situation is someone uses a Chrome browser inside a virtual box inside a VR.  Maybe we already have all the ingredients for this fruit exploit.  But we thought that this situation is not practical.  Moreover, this research seems to need too much work.  Therefore, we changed the situation a little simple.  We just removed the layer of virtual box.  The situation seems to be similar like when the researcher opens the malicious link in VMware.  So the exploit starts from the renderer in guest and ends at the system in host.  So it is the ingredients.  Let's take a look for each vulnerability and its exploitation.  We used 6 unique vulnerabilities.  Three are used in the wild and two are used in Punt1.2023.  And the last is the variant of Punt1.2023.  Because of the time limitation, describing all details about this vulnerability is almost impossible.  However, because all reports are also posted on our blog, you can check if you want.  Let's start from JavaScript code in renderer.  This vulnerability is cv20233079, which is used in the wild.  This is type confusion bug in inline cache for JSStrictArgument object.  First, what is the inline cache?  It is the optimization method for the bytecode v8.  It will register the faster handler according to the time feedback while executing.  Let's look at this example.  After feedback is collected here 10 times, the handler will be registered on the feedback.  Then, if the second time is used again in the future, the registered handler will be used directly to speed up.  In this example, the store handler for SMI is registered as a handler.  Second, what is the JSStrictArgument object?  JSStrictArgument object is a type of argument object used in strict JavaScript code.  Argument object is used to represent the arguments of a function, and it is like array object.  It has elements accessed by index, and also the length is defined.  JSArray looks like this.  There are two size values, length and capacity.  Length represents the number of elements, and capacity is the location size of element's area.  Then, what values are stored in the area between length and capacity?  It is whole object.  This object should not be exposed to JavaScript itself, so VA has to convert it into JavaScript value,  such as undefined or false, according to the situation.  As mentioned before, JSStrictArgument object is like array, but there are many differences.  Among several differences, the main difference related to this vulnerability is the behavior  when a new element is added to the end of array.  As shown in this code, the element kind of JSArgument object will be changed to holy by this code,  but while the JSArray does not.  Let's walk through with this example.  I created an empty array and added one element at the end.  The element kind remains packed element for the JSArray.  But similarly, I create argument object with no element and added one element at the end.  Then, the element kind changes to holy element from packed element.  This vulnerability occurs because improper handler is registered for argument object.  Because of this vulnerability, this storeFastElementIc, growNo, blah blah handler can be registered  as a handler for JSStrictArgument object.  This handler will not change the element kind to holy.  So, in this situation, JSStrictArgument with packed element is possible.  So, what happens in this case?  Unlike JSArray, argument object uses the capacity as the length.  Because the element kind is packed element, the element will be returned directly.  If you access index 1 for this corrupted argument object,  the whole object will be read to JavaScript because the index 1 is less than the capacity.  Then, how can I use the whole object for exploit?  We need to use another bug in JIT compiler.  As shown in this picture, the whole or range-1 and minus-1,  this node will be changed to range-1 and minus-1.  This bug is caused by the JIT compiler not handling the whole object properly  because the whole object does not expose to JavaScript normally.  And then, this wrong assumption will remove the bound check.  However, in the actual execution, the whole object will be interpreted as 0, not minus-1.  So, it causes out-of-bound access in the compiled code.  After then, you can apply the typical way to achieve read-write primitive in V8 heap sandbox.  Yes, there is one more mountain to climb, V8 sandbox.  Because of this mitigation, we cannot read or write beyond the V8 object area.  Obviously, the RWX area is also outside the V8 sandbox.  So, how can we escape this?  The common and popular method is exploiting the low pointer in V8 sandbox.  For our exploit chain, we exploited the low pointer in WASM object.  This is patched now.  The target field of WASM object here remains as a low pointer.  And there is also the function to write arbitrary value to the address of target field in this function.  So, this allows us to arbitrary value to the arbitrary address outside the V8 sandbox.  Also, we can get the address of RWX area because it is stored inside V8 sandbox.  And then, we write the shellcode to RWX area using arbitrary write primitive as I described just before.  And call the WASM function.  Then, we got the code execution.  So, we are now here.  And we can execute arbitrary code in Chrome Renderer.  So now, we must escape the browser sandbox of Chrome.  To escape the browser sandbox, we exploited the Windows kernel vulnerability CVE-2023-21674.  This vulnerability existed in the Advanced Local Procedure Core, ALPC.  ALPC is one of the communication methods between processes on Windows.  In the Chrome Renderer, ALPC is also available including creating port, sending and receiving messages, and so on.  The vulnerability occurs while processing this flag, ALPC message flag and sync request flag in the ALPC message.  As the name of the flag suggests, the flag means that the message requests are processed synchronously.  In other words, the sending and receiving the message should be done consecutively.  When you send a message with this flag, the current thread address will be stored in the waiting thread field,  which represents the thread that will receive the response.  Because of sync flag, the reply process will be executed consecutively while the current thread 1 is blocked.  When the thread 2 replies, the waiting thread field should be changed depending on the state of thread 2.  It will be null or the address of thread 2.  The important thing is that the waiting thread field must not be the address of sender thread, thread 1.  However, there is a way to make the thread field remain the sender thread's address, although the sync flag is set.  That is, the anti-wait for worker factory system call.  This system call only sends the ALPC message without validating the sync flag.  Therefore, if the thread is terminated just returning from this system call,  the waiting thread field will remain as a dangling pointer.  To exploit this vulnerability, we have checked the code that references the waiting thread field.  Using this code shown on the screen, we can change the value at an arbitrary address.  However, as you know, another vulnerability is needed to get the kernel address in the sandbox.  It is hard to apply this method directly, but this method can be used in medium integrity.  Here is another code which references the waiting thread field.  LPCPCOPYREQUESTDATA will get the process address from the waiting thread field, which is already freed memory.  And then it calls mmCopyVirtualMemory to read from or write to the data of that process.  So if you can place the higher privileged thread in the freed memory,  you can make read-write primitive on the higher privileged process.  Using this code, we can make the code execution in medium integrity.  I will talk about the details later.  Anyway, now we are at the user privilege in the guest here.  So to trigger the VMWare vulnerability, we need to elevate the privilege to the system.  For LPE, we used CVE-2023-29360, which is used in Pantone-2023 by Synaptic.  This vulnerability is a beautiful logic bug that allows attackers to map arbitrary addresses.  As shown in this code, attackers can control the address, this value.  And this value will be mapped with kernel mode.  That is, attackers can also map the kernel address by using this vulnerability.  And then we can read from or write to the address through the mapping area.  So we get the read-write primitive combining the address read by anti-query system information.  This will be gone soon.  We can easily get the system privilege.  So now we are at the system of guests.  Let's escape VMWare.  First, we need to know the address information.  For this, we exploited CVE-2023-34044, which is a variant of Pantone-2023.  First, let's take a look at the Pantone vulnerability, CVE-2023-20870, which was found by starapps.  This is a simple uninitialized bug which occurs while handling the USB request block for virtual Bluetooth.  As shown in this code, when the buffer for URB is created, the data is not initialized.  After then, this header part will be set to the appropriate value, but the data part remains uninitialized.  This URB data is finally delivered to the guest as many as the user requested.  Therefore, the uninitialized data is also delivered to the guest and we can get the information in it.  This is the patch.  The patch is quite simple.  The actual length field is set to 8 before response.  8 is the size of header.  But is this code in the red rectangle safe?  It executed before the patch code.  Let's check it.  If the length of buffer's calculated value is greater than 255, an error is thrown without changing the actual length field.  Then, response proceeds.  This is the same situation as previous vulnerability.  To place a meaningful value in the uninitialized area, we use the virtual mouse URB because it has the data section address of VMware VMX.  The exploit process is like this.  First, send the URB package for the virtual mouse device.  Then, after these URB packages are freed, the URB package or Bluetooth device to trigger this vulnerability.  Finally, we can get the address information from the buffer.  Yeah, we are almost there.  Let's escape the VMware.  We exploited the CVE-2023-20869, which was used in Punt1-2023 and also found by Starex.  This vulnerability occurs while processing the Service Discovery Protocol, SDP, of Bluetooth.  This code is the handler for the SDP package.  As you can see in this code, the ElmetType and ElmetSize are both user controllable because they are calculated from user buffer.  If ElmetType is SDPDE unit, that is 1, then SDPData.readLowInt() function is called.  In this function, because we can control the alien value, two buffer flows will occur.  The first buffer flow for the buffer TMP by RBufferCopyOutHeader() function and the second buffer flow occurs by ManCopy() function.  More important part is the second buffer flow.  Because the ManCopy() function doesn't use its own stack, so no stack cookie exists for the ManCopy() function.  In addition, since the minus index is used for the destination buffer, we can override the return address of ManCopy() function.  So by ROP, we can execute WinEXEC API.  Here is the RPChain for our exploit.  As mentioned before, there are two copying processes.  The first copy process is done for the TMP buffer.  And then the state will be like this.  The second copy process is done at a negative index away from SRC.  In this case, because the length is 0x90, the copy will start from SRC-0x80.  So the final state is like this.  After the first article is executed, the state has been changed like this.  And finally, the state is like this, so we can execute Kark command by WinEXEC API.  Finally, we are down to the last step.  The final vulnerability which is used for elevating the privilege on the host is CVE-2023-36802.  It exists in the same driver as the vulnerability used for guest LPE.  As shown in this code, when the publishRx dysfunction is called,  the fscontext2 as the first argument, which is this value.  At this point, we can infer that fscontext2 is a type of fsStringReq.  Because the name is a StringReq object.  Before calling publishRx, the findObject function validates fscontext2.  Let's take a look at the findObject function.  I omitted lots of code, but as shown in this code, fscontext2 can be of two types.  After analyzing this binary, we can find that they are of type fscontextReq and fsStringReq.  fscontextReq has been initialized in this code and the size of the object is  0x78 bytes.  fsStringReq has been initialized in this code and the size of the object is 0x1d8 bytes.  This object is the value that code expects.  So, what will happen if it is fscontextReq, not fsStringReq?  The type confusion can occur.  Because of the size difference, the type confusion will trigger out-of-bound access.  Because the vulnerable object is in a non-paged pool, we can use the named pipe object to control memory layout.  Also, as shown in this code, you can create arbitrary decrement primitives if the attacker can control the value at the offset 0x1c8.  However, we sprayed with the named pipe object.  The header of the object has been located at the offset 0x1c8.  Because the value in the header is hard to control by attackers, we need to use another way.  To solve this, we took the approach of utilizing other objects.  We utilized thread name object instead of named pipe object.  Similar to named pipe object, with this object, we can create the memory of any size and store the data you want and release it when you want.  But this object has only 0x10 bytes header, while the named pipe has 0x30 bytes.  Therefore, the layout will be changed like this.  Because we can control the data in offset 0x1c8, we are able to trigger arbitrary decrement primitive.  Eventually, you can change the previous mode of current thread to 0 by this primitive and then duplicate the system token to get the system privilege.  Finally, we reach to the system host.  This concludes the introduction of vulnerabilities and its exploits.  After then, we need to chain these vulnerabilities.  There are many ways for chaining them.  This section will describe about what we have tried.  First, chaining the renderer and sandbox escape exploit.  We need to make the shellcode about whole exploit process to chain them.  But it is so difficult and inconvenient.  So many exploits utilize the helper class, which allows attackers to write their exploit code as JavaScript.  Punjs is one of the helper class for exploit.  It was developed by our company, but sadly, it is not maintained for 5 years.  So I wrote own helper class for this.  This is the power of the exploit code.  With the own helper class, I can embed the sandbox escape exploit code as JavaScript, like this.  And then, I will pick up where I left off.  For the sandbox escape, I have set up the strategy like this.  To achieve this, we should spread the threat of the higher privilege process.  Which process is suitable?  We first try to find a way to create the system threat, but it is not easy.  We try to find a way to create the system threat, but it is something hard due to the limited permission in the sandbox.  So we turned our attention to another processes.  One candidate was audio process of Chrome.  We can easily create the threat of that process by this code.  However, when the audio threat is created, the renderer threat is also created.  It reduces the probability of audio threat taking up the free memory.  In addition, audio threat has many mitigations, which makes exploit more difficult.  The second option is file picker process.  Just calling this function should open file picker.  The file picker window is created as a new process.  This process is medium integrity with few mitigations.  File picker windows will generate 25 to 30 threats, and they have been placed at the free memory with high probability when I pass it.  Now we select the target process and we can rewrite on that process.  Then how can we run the arbitrary code?  To make the arbitrary code, we overwrite the global variable which contains the object address.  Using the arbitrary redirect primitive, construct the fake object at the empty area,  and then overwrite the global object to the address of fake object.  When the global object returns, the exploit will be triggered.  There are some candidates for global variable to overwrite.  We have used the GActive verifier for our exploit.  This is referenced when the file picker window is closed.  Next, how did we construct the fake object?  There are many ways to construct.  In my case, to construct the fake object, we used two gadgets.  The first gadget is this function.  This gadget can be used to connect function calls of two objects.  The second gadget is this function.  This gadget allows attackers to invoke an arbitrary function with desired arguments.  So this is the full structure of our fake object.  First, the function calls of object 1 and object 2 will be connected by the first gadget.  Object 1 is used to allocate RWX memory.  Object 2 is used to connect object 3 and object 4.  Object 3 will copy the share code into the RWX area.  Finally, object 4 will jump to the share code.  So we got the arbitrary code execution outside the Chrome sandbox.  The LP is easily connected.  I skipped the part.  The final problem is the limited space for the commands in WinEXE's API.  To chain with LP exploit on host, we need to create a directory, download the exploit binary, and execute it.  Maybe the powershell command is the best option, but the space is too small.  So this space is only possible for the command line.  To solve this problem, elaborating the outer chain is an option.  But we choose to use different memory space for the command line.  So we use the physical memory of guest OS.  From the host OS perspective, the physical memory of guest OS is treated as a mapped memory.  And each address can be obtained from VMWare VMX memory.  So we just need to add one more RP gadget, which gets the address of mapped memory and puts it into the RCS register.  The rest of the RP chain is the same.  So that's the full story for our exploit chain.  It's been a good experience for us, and we learned a lot for each system.  Connecting each vulnerability makes them much more powerful and lots of fun.  So maybe we'll be back with more interesting research, since we still have lots of ingredients in our database.  I will end my presentation. Thank you very much.  Wonderful. Thank you, Jahal.


url: https://www.youtube.com/watch?v=cDcMlMH-XjU
title: Off-By-One 2024 Day 2 - Love and hate - The cyber tale between fuzzer and exploits in Linux kernel
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=cDcMlMH-XjU",
    "title": "Off-By-One 2024 Day 2 - Love and hate - The cyber tale between fuzzer and exploits in Linux kernel",
    "description": "Abstract\n\nContinuous fuzzing has become an integral part of the Linux kernel ecosystem, discovering thousands of bugs over the past few years. Interestingly, only a tiny fraction of them were turned into real-world exploits that target downstream distributions, e.g., Ubuntu and Fedora. This contradicts the conclusions of existing exploitability assessment tools, which classify hundreds of those bugs as high-risk, implying a high likelihood of exploitability.\n\nOur study aims to understand the gap and bridge it. Through our investigation, we realize that the current exploitability assessment tools exclusively test bug exploitability on the upstream Linux, which is for development only; in fact, we find many of them fail to reproduce directly in downstreams.\n\nThrough a large-scale measurement study of 230 bugs on 43 distros (8,032 bug/distro pairs), we find that each distro only reproduces 19.1% of bugs on average by running the upstream PoCs as root user, and 0.9% without root.\n\nRemarkably, both numbers can be significantly improved by 61% and 1300% times respectively through appropriate PoC adaptations, necessitated by environment differences.\n\nSpeaker\nZou Xiaochen is a Ph.D. candidate at University of California, Riverside, advised by Professor Zhiyun Qian. Xiaochen earned his bachelor degree from University of Electronic Science and Technology of China.\n\nFollow Xiaochen on X @ ETenal7",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2162,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240901"
  }

  This text was transcribed using whisper model: large-v2

   Hello everyone, good morning or afternoon.  I don't know what time is it in Singapore right now.  I hope you have enjoyed the weather and the food.  I really wish I could be there to watch all your talk and have great conversation with  you guys.  But due to the visa issue, I am not allowed – like, I am allowed to leave U.S., but  I don't want to risk my visa to leave the U.S.  That's why I give this video talk, and I'll have a live Q&A afterwards, I guess.  So my name is Xiaochen Zhou, I'm a senior year PhD student at UC Riverside.  Today I'll present my recent work about Linux kernel bug exploitability assessment.  I call it Love and Hate, the cyber tale between father and exploits in Linux kernel.  This work has done by me and Professor Jun Qian.  Yeah, let's get to our – bugs are errors that cause computer program to behave unexpectedly.  Most of the time the normal behavior only cause minor issues, or sometimes we don't  even notice.  However, some bugs are much more severe.  So one day people realize this severe behavior could lead to a total compromise of the application.  We call it exploits.  And for all these bugs that can lead to exploits, we call it exploitable bugs.  Now all these years, security researchers have developed different ways to discover  exploitable bugs.  So in the beginning, we start with manual code auditing.  We read hundreds of thousands of lines of code with our bare eyes to just find one tiny  variable misuse or missing log.  I really admire those people who can do the manual auditing, and they're the hero of cybersecurity.  Well, in later stage, people find manual auditing is low-efficient, so they build program to  find bugs.  Because we have two automated solutions for bug hunting, dynamic way, aka fuzzing, and  static analysis, the static way.  But with the decades-long iteration, some software become shockingly huge.  For example, Linux kernel source code contains 28 million lines of code and countless indirect  call and global cross-reference and dependencies.  That creates plenty of problem to manual auditing and static analysis.  However, by the nature of a dynamic approach, fuzzing won the competition with unbeatable  efficiencies and the lowest false negative rate.  But one problem with fuzzing is the blindness, which means we have less control during the  fuzzing process.  Randomness seeds are generated, and test cases are guided by coverage feedback.  All these undeterminable factors add up to the blindness.  So sometimes, we may find a lot of bugs.  We find a lot of bugs, but none of them are security bugs.  And less security bugs means less exploits.  So this suspicious gap between the fuzzing-exposed bugs and the real-world exploits is what we  want to discuss in this talk.  But can we make more fuzzing-exposed bugs to be exploitable?  So the first question is, is Linux kernel really safe?  Here is an excellent Linux kernel security channel on Telegram.  They collect every Linux kernel exploit write-up that we can find online.  And here are samples of kernel exploits from 2033 to 2024.  That's like 10 to 20 exploits every year.  Like 20, 10-ish, 20-ish exploits sounds like a reasonable amount.  But if I tell you how many Linux kernel bugs out there, you will be shocked.  So let's introduce Sysbot.  So Sysbot is a fuzzing platform developed by Google.  It deploys Google kernel fuzzer, syscaller, to fuzz Linux kernel 24 hours a day and seven  days a week.  The Sysbot is so powerful, it funds so many bugs that even overwhelm the kernel developers.  So they don't have enough time and resources and people to fix all these two to three new  bugs every day that are found by Sysbot.  In the past six years, Sysbot has found more than 10,000 kernel bugs.  And up to now, there's still a thousand bugs that are not fixed by Sysbot.  Well, not fixed by the developer.  They were found by Sysbot.  So if you look at this graph, this graph, the red line is the new bugs, open bugs.  And the green line is the fixed bugs.  So you will notice there's a gap between the green line and the red line.  That means the bugs is unfixed.  And this gap expanding every year.  In March 2003, the gap has become 6,000 bugs, that means 6,000 bugs has not been fixed at  that point.  Well, this gap has been snubbed back due to multiple reasons, like after the code iterations,  so some bug may be silently fixed or become invalid.  Despite the huge number of unfixed bugs, thousands of them, why we didn't see a clear spike of  kernel exploits in the past few years, still only 10 to 20 exploits in the past every year?  Well, so our current situation is like this picture.  We have a significant amount of kernel bugs, but we have only so little exploits.  Why did that happen?  To answer this question with confidence, we need to learn some background knowledge of  fuzzing and of Linux kernel.  The fuzzing pros and cons.  The syscaller is so efficient, it generates hundreds of valid test cases per second.  I say valid test cases, that means syscaller knows the many kernel dependencies according  to the manual graph database.  So on the left-hand side, this picture is what we call description.  This describes the kernel dependencies to the syscaller.  The syscaller will understand this.  For example, this simple program, the socket will return a file descriptor, and this file  descriptor will be used by other system calls.  This is one typical dependency.  Because syscaller knows this dependency, it can generate the valid test case very fast  and find the bug with efficiency.  For example, in order to find the bug hiding here, deep down in the kernel space, syscaller  will call different system calls in a sequence, and each system call will make the kernel  enter a specific state that's a dependency.  So calling system call 1 will enter a kernel state, and calling system call 2, because  the kernel is set to write state, we can go to state 2, and call the final system call  will trigger the bugs.  And more importantly, the dynamic approach fuzzing, it generates a concrete test case  after finding a bug.  So we will have a concrete POC that can actually trigger the bug.  Neither static analysis or manual auditing can do this job.  So fuzzing is so efficient, but it's blind.  It generates test case based on randomness, which means it does not do any favor of finding  security bugs.  Actually, finding bugs is fuzzing all care about, regardless if they are security or  not.  And even worse, in order to find more bugs, kernel fuzzers are developed by good privilege,  are deployed by root privilege.  This equips fuzzer with better chance to explore bigger code space in kernel, without worrying  being rejected by the privilege problem.  However, as security researcher, if a bug has to be root to trigger, we're not interested,  because they are not exploitable bugs.  They request root, what's the value we exploit them.  But okay, we've been talking to these two major problems about fuzzing, but even with  all these flaws and problems, C-Spot is still very efficient and still managed to find a  significant amount of security bugs in the past six years.  So 24.1% bugs found by C-Spot are memory errors.  And memory errors like use-after-free or auto-bound and double-free, they are memory errors.  And among these memory error bugs, 18.2% are likely exploitable bugs.  So we are talking about use-after-free write, auto-bound write, and double-free.  So they are the most common exploitable bugs that are on the market.  That gives us 232 likely exploitable bugs.  Well, that's actually a very big number, considering we only have so little exploits every year.  And another research, actually my previous research that published in Usenix Security 2022,  we assessed the bug capability, and we realized the bug initial capability does not represent  the most critical capability.  So that means a lot of low-risk bugs, like memory read bugs or warning or other low-risk bugs,  they can be converted to high-risk bugs.  So they contain the high-risk capability.  The number can only be more than 232 bugs that are likely exploitable.  So there are so many likely exploitable bugs, but we still find so little exploits.  So for the bugs that originated from C-SPOT, there are only around seven that I can find on the internet.  Well, there are more kernel exploits, of course, besides originating from C-SPOT,  but now we're only talking about the one big database, it's the upstream C-SPOT, upstream kernel bugs.  So there's only around seven, 232 versus seven.  That's kind of shocking.  Well, another inconspicuous factor contributing to the gap between the bugs and exploits is the structure of the Linux community.  So Linux has upstream and downstream.  Upstream kernel is where people are developing and debugging, and it's not a daily-use kernel.  But upstream kernel is ideal for bug-finding, and C-SPOT deploys its fuzzer only on upstream kernels.  So here I mentioned upstream kernels, that includes all the upstream branches,  like long-term support branches or Linux Next branches, not just the upstream kernel.  However, nobody used upstream kernel in production environment.  The stable upstream kernel branches will be pushed to downstream once in a while.  So based on those stable upstream branches, the downstream will have different distros,  and we have Ubuntu, Fedora, Debian.  Most importantly, they are stable and well-maintained,  so people are using it on a daily basis in their production environment, and that's why it got attacked.  So nobody attacks the upstream kernel because nobody is using it.  That's why people are always attacking the downstream kernel.  That causes a problem because upstream fuzzer-exposed bugs can trigger a bug on upstream kernel,  but it may not trigger the bug on downstream kernel.  But this does not mean the downstream kernel is not affected by this bug.  Their triggerability is not equal, but their POC can be adapted to downstream, making it triggerable.  So we visualize this gap between upstream fuzzer-exposed bugs and kernel exploits.  It's not just the imperfection of the bug itself.  It's a long-existing gap between the upstream and downstream.  The major difference in these two kernels causes the asymmetric number of upstream bugs and downstream exploits.  So is it possible to turn more upstream fuzzer-exposed bugs to downstream exploitable bugs?  We want more bugs, more exploits, or even like this,  we want every upstream bug to be exploitable.  Well, not quite possible, but we can think about it.  So how to make it happen?  Our first step is to understand how many upstream bugs can actually be reproduced in downstream kernel.  So we have designed an experiment.  We prepared four downstream distros, Ubuntu, Fedora, Debian, and SUSE.  Next, we gather 50 upstream kernel bugs from six bugs,  and then we run their POC against all four real-world distros.  And we choose the major release that is close to the bug discovery date.  So which means, for example, if a bug was found in September 2021,  we will choose, for example, a Ubuntu release that closes to September 2021,  which might be the June release.  By doing this, we make sure the bug always reproduces on a vulnerable version,  or the patch will not exist in the prior version because the bug was found afterward.  So 50 bugs for four distros.  We got 200 bug and distro pairs.  We found 120 pairs that failed to trigger the bug  because the distro does not have the bug you can meet.  That means the bug was never introduced.  For the rest 80 pairs that were vulnerable to the bugs,  we find only 18 of them have successfully triggered the bugs,  but all of them were triggered by root privilege.  So none of them are exploitable bugs because they require root privilege.  For the remaining 62 bugs that have failed,  we find 41 of them failed due to logic missing.  That means the vulnerability code exists in the kernel source code,  but it does not exist in the kernel binary,  most likely because they are not compiled.  This is a common case that the downstream distro  will not compile every single upstream kernel module,  even though the bug you can meet exists.  But not compiling the kernel into the binary means the same as the no bug you can meet,  is that the distro is not affected by the bug.  For the remaining, we find one pair failed due to the code context change.  That means the vulnerability logic has been completely rewritten,  and thus the old POC cannot trigger the same bug,  and 20 other pairs have failed due to what we call environment change.  The environment change will be the main topic for the following talk.  We categorize the failure reason of the environment change.  You will see their number adds up to be more than 100%  because one bug could fail due to multiple reasons.  The first failure reason of the environment change is what we call preparation failure.  One typical example is setting up the USB fuzzing.  This caller will try to open a device called rawgadget.  This rawgadget device exposes the USB interface,  so you don't need actual USB hardware to interact with the kernel USB logic.  Instead, directly interacting with this rawgadget virtual device,  it makes testing USB interface possible for the kernel fuzzing.  However, due to the blindness of kernel fuzzer,  it may find a completely irrelevant bug rather than a USB bug.  While fuzzer doesn't know that, it will still think it's a USB bug  and it will keep the USB preparation function in the POC.  However, the downstream kernel will not have this virtual interface  because you always use actual hardware USB device when you're using Ubuntu.  When the POC tried to open this rawgadget device, it failed  because this path does not exist.  Oftentimes, if a POC fails, like the preparation has failed,  they will terminate itself and exit.  That makes the POC not reaching the core POC function.  They will terminate before reaching the POC core function  and make the bug not triggered.  Another reason that upstream POC failed is because of the background noise.  In upstream kernel, there are only a few background processes running  and the POC process can easily win the data race.  If a risk can be found, it can easily win the data race and trigger the bug.  However, in downstream, there are much more services running in the background,  so the chance of the POC process can win a data race is much lower  than in the upstream kernel.  For example, we have SSH, we have APT, we have some desktop environment processes.  If this kind of find, the minimal resource can trigger a bug in upstream,  it will generate the POC, only use that minimal resources.  We are talking about the number of CPU cores, number of iterations and processes.  Sometimes the upstream can even trigger a risk condition bug with only one attempt.  At that point, SysConnect will even not think it's a risk condition,  but think it's just a normal bug and generate POC according to that.  And the same POC likely failed on downstream.  The third further reason, I always take 50% of the case, is the missing module.  For further inconvenience, the kernel modules are always compiled into the kernel binary,  versus downstream distro often compile them as separate loadable modules.  Therefore, the upstream kernel have every module ready to use.  In this case, a valid case can always successfully interact with the desired module and trigger the bug.  However, downstream kernel, choose another way, they compile such module but not load it by default.  You have to load it yourself as needed on demand.  If the desired module is missing, the kernel will choose either return an error,  or choose a default module to perform the operation.  And because it's not doing anything to the vulnerable module, the same POC will fail to trigger the bug.  So to overcome these three problems, we came up with three automated solutions.  For the preparation failure, we minimized the environment preparation steps to rule out the unnecessary steps.  So if a POC can still trigger the bugs in upstream without these preparation steps,  we think they are unnecessary steps, so we will rule out the unnecessary steps to only retain the necessary steps.  And after removing the unnecessary preparation function, we can successfully reach the POC core function and trigger the bug.  The second solution for the background noise is, well, the upstream kernel is the minimum kernel,  and it has so little services running in the background, and it's very easy to win the data race, as we already know.  And here, this is the resources for the data race.  So the POC process can easily win the resources and trigger the bug.  But the same POC on downstream is very different.  There's more processes competing the same resources,  so you will often find the POC function fail to win the data race with other processes.  So our solution is we force the data collision.  That means more CPU cores and infinite for loop and longer execution time.  By doing that, you will find your POC process eventually win the data race and trigger the bug.  Okay, for the third problem, the missing module.  To find the missing module, we use ftrace to extract the execution trace from both upstream and downstream.  Then we compare the execution trace to find the deviation point.  In this example, we notice the deviation point start at node 3, where the upstream called xfrm since they notify,  while the ubuntu called another function.  This caused the ubuntu fail to trigger the bug.  But in order to trigger the bug in ubuntu, we need to first load the xfrm user module.  Well, this module already compiled in the upstream kernel, so only ubuntu need to load this module.  And a common way to load module is through mode probe.  And that is the privileged operation, which means you have to be root user to load the module through mode probe.  But we find a way to load this module by unprivileged user, which we will talk about later.  If you still remember, all these previously triggered bugs were all triggered by root user.  So we are thinking, is there a way to make them triggerable by unprivileged user?  There are several privileged checks.  One is the capability check is well known.  And the privileged downgrade technique is also well known.  So kernel uses this capability to provide fine-grained control over the large code space.  The low-level kernel function ns cable common checks the process capability.  So the ns is the namespace, and the cap is the capability.  For example, this code snippet checks if the current process namespace has the capability cap net admin.  Luckily, this capability can be granted in user namespace by unprivileged user when the unprivileged user ns clone is set to 1.  But most distros, like 1, 2, Fedora, Debian, Suse, they all allow unprivileged user namespace.  So this is doable. It can be granted by normal unprivileged user.  However, not every capability can be granted by user namespace.  If a capability checks the initial namespace instead of the user namespace, a normal user cannot get such capability.  Only a real root user can do that.  So we monitor this low-level kernel function to know if POC requires a real root capability or user namespace capability.  If it only requires a user namespace capability, we will grant them to the POC.  Another privileged requirement is the module loading.  As mentioned earlier, the universal way to load a module is through mode probe.  Mode probe invokes the system called initial module.  And the initial module checks whether the process has the cap system module capability.  Unfortunately, this capability, this function checks the initial namespace.  That means only root user can call mode probe and unprivileged user cannot have such capability.  That's why the mode probe can only be run by root privilege.  But we find another interesting kernel function called request module.  And we find plenty of request module call sites across the whole Linux kernel.  And some of these call sites even have a format string to pass the module, to pass the minor number to the actual module name.  So you will see there are different number indicates different network modules.  So one request module call site can load multiple module.  To understand how request module load a module, we look at the source code.  And we find it first get the mode probe user space pass.  And then they get the final module name from the format string.  And the module name will be passed to the call mode probe function.  Well, from that name, you already guess what this function does.  The call module name will prepare the arguments.  The first argument is the pass.  And then we have the module name over here.  And then they do an op call to user space.  So this op call will, interestingly, this op call will be executed as root.  They will call the mode probe by root user.  So we have a new concept of how to load a module.  An unprivileged user somehow call a request module kernel function through some system calls.  And this function proceeds an op call to user space and root user.  This root user executes the mode probe to load the dedicated kernel module for us.  So we are actually asking a root user to load module for us.  Like very cool. That's very cool.  So instead of calling mode probe XFRM user to load a module, which requires root privilege, by the way,  we can simply call this system call with unprivileged user.  So that makes our unprivileged user very happy, you can see.  And that's just one example.  But we want to know how many, like what is the module that can be loaded by unprivileged user  and what module cannot.  By simply searching the request module, we find there is 249 call sites across the kernel source code.  And a lot of them, they are format string.  That means one call site can load multiple kernel modules.  So we're thinking, well, is there a possible we can load arbitrary module,  like we get a module name directly from user space  and we pass this argument directly to the request module.  By doing that, we can load arbitrary modules.  So we don't need root privilege to load even like very critical module.  But the kernel developer found that stupid.  So we couldn't do that.  We didn't find anything like that.  So we have to collect or categorize every single request module site and their loadable module.  But this problem is very exhausting, but by the nature of the problem,  that makes us thinking about the only effective approach, which is fuzzing.  Although we have been talking down about fuzzing all along,  but nothing can do the same job as providing concrete test case and invoking kernel call sites,  only fuzzing can do that.  So we build our customized request module fuzzer.  We intentionally instrument the request module function to notify the fuzzer  and we reproduce the results by unprivileged user to make sure that the normal user can load such module.  Our fuzzing results turn out to be very good.  We find hundreds of normal user loadable modules across all four distros.  The number has the network has the most module.  Well, this is a sample of the modules and that's not all of them.  And next is the crypto.  And then we have file system.  Please note that loading a file system module by normal user does not essentially mean you can mount the file system by normal user.  So mounting is another privilege operation that only a few file system can be mounted by normal user,  like fuse or overlay FS.  And it's time to do some number crunching.  We prepare 282 likely exploitable blocks that contain at least one of the following high-risk primitive used after free write,  out-of-bound write, double free, counterflow hijacking, arbitrary address write and constrained address write,  arbitrary value write and constrained value write.  So they are all high-risk capability and make the bug to be likely exploitable bugs.  So without any adaptation by running the original POC as root privilege,  we want to see how many bugs can be triggered on the downstream kernel.  On average, 44 out of 282 can be triggered.  And that's 15.6 percent.  Ubuntu 54, Fedora 48, Debian 47, Suse 27.  Then we applied our automated adaptation to all the 282 POCs.  And we increased the number by a lot.  And now, by average, we have 73 out of 282 bugs.  That's 25.8 percent.  We improved the result on average 65.9 more.  We do the triggerability test by root privilege.  But because they are likely exploitable bugs, we want to know how many of them are actually likely exploitable on downstream.  So we have to run the POC again by normal user, by unprivileged user.  So now we do it again by running them with unprivileged user.  The result is very bad.  Only 1331 bugs can be triggered on Ubuntu, Fedora, Debian, Suse.  That's on average 0.7 percent.  Well, we have this question why there's so little exploitable bugs on so many bug databases, so big bug databases.  This result somehow proves that's why there's so little sysbug bugs were turned into real world exploits.  However, after applying our privileged adaptation, we dramatically increased the number of normal user triggerable bugs.  So for Ubuntu, we increased the number from 1 to 35, Fedora from 3 to 50, Debian from 3 to 31, and Suse from 1 to 9.  Well, on average, 31 out of 282 bugs, that's 25.8 percent.  We improved the results by 14 times.  Note that these bugs are all likely exploitable bugs.  Comparing the past, there's only 7 bugs were turned into real world exploits.  The bugs from sysbug, only 7.  To prove the effectiveness of our tool, we picked one unfixed bug at a time for our results.  And we successfully developed n to n exploits to escalate the local privilege on the latest Ubuntu.  And we plan to use that exploit, participate in the Pontoon event here.  But unfortunately, the bug was tragically fixed one month before Pontoon.  Well, so we didn't get a chance to participate, but at least the exploits proves the effectiveness of our adaptation method.  So here are three case studies that we find interesting.  Well, their original POC cannot trigger the bugs on any downstream.  Bug 1 requires additional module.  Except if I'm a user, we talk multiple times, you can use this simple system call to load such module and then you can trigger the bug.  The bug 2 requires RDMA UCM module.  Loading this module is a bit complicated.  You need two system calls and a well-prepared data structure.  After you run this program to load the module, you can trigger the bug.  Well, bug 3 is even more complicated.  It loads IPv6 tables, which require a sophisticated data structure.  And this module uses alias in the request module, not the IPv6 table name.  This alias is ICMP6.  You have to use that alias, but our father managed to find a concrete POC to load that module.  And after loading that module, we can trigger the bug.  So the key takeaway from this talk, upstream and downstream have different environments.  And fuzzing is efficient on upstream kernel.  And fuzzing neglects the privilege and environment factors.  And the fuzzer-generated POC often failed on real-world OS.  But real-world OS may still be affected.  And don't give up.  Remove unnecessary preparation steps.  And allocate more resources to the POC.  Finding missing kernel modules.  And the privilege requirement can be downgraded.  Check whether the namespace can bypass the capability.  And if there's any missing modules, check whether they can be loaded by unprivileged users.  Because the unprivileged user is capable of loading hundreds of kernel modules.  I think that's everything about my talk.  And you can access my portfolio by scanning this QR code.  I also have my CV.  Also, I'm in the job market in 2025.  I will be graduating soon.  I'm looking for a security-related job.  Well, I think I'll have a live Q&A somewhere here.  I'm ready to take questions.


url: https://www.youtube.com/watch?v=mpRIvN5Kzhs
title: Off-By-One 2024 Day 2 - Attacking the Samsung Galaxy A Boot Chain
type: video
author: Off-By-One Comms Team
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=mpRIvN5Kzhs",
    "title": "Off-By-One 2024 Day 2 -  Attacking the Samsung Galaxy A Boot Chain",
    "description": "Abstract\n\nDuring our past research analyzing the Android Data Encryption Scheme, we dived into the boot chain of Samsung low-end mobile devices, in particular the Galaxy A family, which is based on Mediatek System-on-Chips. These devices are often overlooked by the security research community, which usually targets high-end ones (e.g., the S family for Samsung). Nonetheless, these devices are extremely popular, and thus represent a big share of the phones in the wild.\n\nOn top of the Mediatek boot chain, Samsung added its own features including Knox Security Bit, support for their recovery tool Odin, a JPEG parser and so on.\n\nIn their latest system of chips, Mediatek have improved their security, and fixed an infamous BootROM vulnerability that used to impact most of their chips.\n\nYet, even with the security improvement done by Mediatek and the apparent security brought by Samsung, we were able to break the boot chain of most of the Samsung phones powered by Mediatek SoCs.\n\nWe will present several 0-day vulnerabilities that, chained together, can be used by an attacker with physical access to a wide range of Samsung devices (mainly from the A* family), to bypass the secure boot, execute code on the chip, reach persistency and ultimately leak the secret keys protected by the hardware-backed keystore.\n\nThis presentation brings together two important concepts of modern mobile architectures: the secure boot and the Trusted Execution Environment. It gives a comprehensive view of how these features work and how they can be targeted by security researchers, focusing on the offensive approach.\n\nSpeakers\nMaxime Rossi Bellom (@max_r_b) is a Security Researcher and Tech Lead working at Quarkslab, focusing on the hardware and low level software security of mobiles devices and embedded systems.\n\nHe likes playing with secure boot, and security chips embedded in smartphones.\n\nDamiano Melotti (@DamianoMelotti) is a security researcher. He is mostly interested in systems security, especially in mobile platforms (Android) and automated vulnerability research.\n\nGabrielle Viala (@pwissenlit) is a security engineer specialized in vulnerability research and exploitation at Quarkslab. She is usually focused on desktop-based components, but as long as the project involves low-level technology, any target can be a good playground for her.",
    "channel_url": "https://www.youtube.com/channel/UCmrsIbKdxEMBEefD8v8RigQ",
    "duration": 2553,
    "channel": "Off-By-One Comms Team",
    "uploader": "Off-By-One Comms Team",
    "upload_date": "20240901"
  }

  This text was transcribed using whisper model: large-v2

   All right, hello everyone, I hope you can hear me fine.  It's good to see many people here and we're happy to present the talk today that is going  to be on attacking Samsung Galaxy A family of devices and in particular their blockchain.  Well, we already received a very good introduction, so maybe I can go quickly on this slide, but  this is a research that started last year while working at QuartzLab and today here  we have me, Damiano and Maxime who is going to join me on stage shortly.  So this research actually started from a previous research that we had done the year before  on the Android data encryption scheme.  In this particular research we wanted to figure out the details of how data encryption at  rest works in modern Android.  So what we did was we took a form that had an existing known vulnerability that we could  exploit and we played with the various internal components that are involved with the encryption  of essentially the data that you end up storing on your device.  We wanted to know how an attacker would go and try to defeat the schema, how the password  or any authentication factor of the user is involved in the process and we ended up  kind of building a bit of a picture of how this whole thing was working.  What we're trying to show today is essentially the same thing, but instead of relying on  an existing vulnerability, we show how starting from the USB stack you can effectively obtain  the same results.  So we are working on, we said, the A family of Samsung Galaxy devices.  Here's the specific model we used.  It's sort of in the low end part of devices.  It's relatively cheap.  And it runs MediaTek SoC.  So there is this mix of MediaTek and Samsung code that is running on the phone.  Obviously Android is the OS and for the trusted execution environment that we will be talking  about in the talk, the device is Tigris, which is the one developed by Samsung.  And again, there is a node from Bug that is exploitable using MTK Client, a nice tool  that was built to exploit this bug and bypass the secure boot.  So we didn't use it in the chain, but it was definitely helpful to make debugging easier.  So before diving into our work, a bit of introduction.  And we start from the MediaTek secure boot process.  There are various components involved, obviously.  And the first one is the bootrom, obviously.  So the very first piece of software that starts executing.  The bootrom spawns the preloader, which is the second stage bootloader, which in turn  starts three different things.  On top you see the Arm Trusted Firmware, which is also known as Secure Monitor.  This will stay in execution in the highest privilege level of the secure environment.  Then we have Tigris.  Tigris is the trusted execution environment operating system.  It has both a user run and a kernel, so it runs on two different exception levels.  And then we have Little Kernel.  Little Kernel is the main Android bootloader running on VM1.  And this will launch Android, so the kernel can be deployed.  So we will start our talk from Little Kernel, so the main Android bootloader.  But before diving into that, another little bit of introduction on Android partitions.  This is just to say, this is just to kind of put everyone on the same page.  Android is usually shipped in different partitions that serve different functions,  and that you can flash or restore independently, more or less.  So for example, we have the boot image that has the kernel and run this.  VD meta is used for verified boot.  But then we have dynamic partitions that are only parsable by user run.  So the super partition is the best example with the system vendor.  If you are familiar with Android, these names ring a bell.  If you're not, just imagine these as the building blocks that you can flash on your operating system.  And yeah, Little Kernel has its own partition.  And Little Kernel in general is actually an OS by its own.  But it's very common as a bootloader in the Android world.  It implements some features to recover parts of the system.  And in particular, it implements Android verified boot,  which is the feature that allows to have secure boot and verification of Android images,  as well as broadband protection.  So Samsung took Little Kernel and modified it to include some custom features,  such as the Odin recovery protocol, which is Samsung's protocol to recover partitions and flash them.  Also to update, these kind of things.  Then we have the Knox security bit.  Knox is a suite of tools that is meant to improve the security of Samsung devices.  In particular, the Knox security bit is a way to essentially void warranty when a bootloader is unlocked.  And then we have also a JPEG parser and renderer,  which is used to render errors like the ones you see here on the right.  So in case something goes wrong at boot time, you have this nice message that tells you what happened.  So this version is closed source, honestly.  Since Little Kernel is open source,  various engineering is not too complicated because you can help yourself with the open source version.  So Max will promise this now and we'll get to the fun stuff.  Thank you, Leonardo. I hope we can do well.  So the first component that raised our interest was the JPEG parser,  the one implemented by Samsung.  And this is because the JPEGs are placed into a tar archive that you can find in the partition called app.params.  And this archive is signed, but the signature is never checked at boot.  So anyone with the ability to modify the internal memory of the device can actually modify this JPEG.  So as a security researcher, it's kind of an interesting primitive.  And we all know that sometimes parsing images can be a difficult task.  Here we are citing LogoFade, which is a research by Barnaby that was presented last year.  They fuzzed a couple of simple image parsers in different bootchains and they discovered many bugs.  So this is definitely something interesting for us.  And before we get into this parser, we need to understand how these JPEGs are loaded in Little Kernel.  So this is the code responsible for that.  And as you can see, the first step is that there is a constant size allocation on the buffer of one gigabyte.  Then you have this function that we call readJPEG file.  So the name is the one we get from reverse engineering.  But you get the idea.  This function will take the file name as the first parameter,  and it will read the corresponding file name as an archive,  and then load the content into the buffer that was previously allocated.  And finally, you have this big image function that will parse and render the JPEG on screen.  Now some of you may wonder why we have this 0 as the third argument of the readJPEG function.  Actually, this third argument is supposed to be the maximum size.  So whenever the system looks for a JPEG in the target,  it will first read the size from the header.  And if the size is bigger than the one provided, it will trigger an error.  So the size will not be read.  Unless the size provided is 0, in that case, well, the check is ignored,  and the file will be read in the buffer.  So we have here, first, a minorality for us.  It's a heap overflow.  The question for us now is, is it exploitable?  So to answer that question, we need to understand how the heap algorithm works.  And in this case, you can tell that by default, we have a mini-heap,  which relies on a double-heap list.  So we have a list of free chunks.  It's all actually all placed in the same memory pool.  They're all following each other.  And they all start with the header you see on the right.  So we have a pointer, prep, pointing to the previous free chunk,  and the pointer prep.  Then another pointer pointing to the next memory chunk,  and then the size, and then the contents of the chunk.  So if another flow happens, we may override the header of the next chunk,  which includes these pointers.  And we found a way to turn this into a mandatory write.  This is because of how the allocation routine works.  So when the system allocates a chunk, a memory buffer,  it will remove a chunk from the free list.  And to do so, it will dereference the next and prep pointers of the chunk being allocated  in order to access the previous and next chunks in the list  to, in turn, modify the pointers next and prep of these two chunks  so that they point to each other and not to the previous chunk.  So it means that, basically, we can control these two pointers next and prep  of the chunk being allocated.  It leads to a write that we are permitting,  with the only constraint that both values must be writeable addresses.  Now, a few words about the mitigations in our relative canaries.  There are not many, as you can see.  No AS at all, no canaries, and more importantly, the heap is executable,  which makes the exploitation rather simple.  It's quite convenient for us.  So the exploit strategy becomes something like this.  We use our primitive to overwrite a pointer which we call the chunk to,  such as the return address in the stack, in this case.  And we will make it point to a shellcode that we place inside our JPEG buffer.  So to highlight this with a nice schema,  here we have a representation of the free list.  And you see in purple the JPEG buffer that we just allocated.  So the next step is that the system will read the JPEG and will feel the buffer.  And at some point, it will overwrite.  We will overwrite to the next free chunk.  And we will replace it with a fake chunk, let's call it like this,  where the next pointer points to the return address in the stack,  and the prep pointer points to the shellcode.  Such that when the next allocation happens, the system will deliver chunks next,  and it will replace the return address with the address of the shellcode.  And you know what comes next, I guess.  When the function returns, we execute our shellcode.  So this is the theory.  And to validate that, we implemented a little emulator.  So we use Unicode for that.  I'm sure you're probably all familiar with Unicode.  It's a CPU emulator, meaning that it cannot be used to emulate a full system.  So, for example, no interruptions.  No hardware, no interaction with hardware.  But it's not really a problem in our case,  because we can really isolate the data that we want to emulate.  And it's also very straightforward and easy to use.  So we implemented this little emulator in which we exploited this variability.  But the problem we have then is that the same exploit will not work on the real device.  And there are a couple of things that are actually going wrong.  The first of them is that the heap and the stack will be present in both environments.  And the way we solved this was to use the bootramp variability that we described.  So we basically used this variability to bypass the sector boot.  We patched the exact same heap and stack and imported it into an emulator.  There is another way to do so, which we rely on reverse engineering,  because we don't really care about what is inside the memory.  We only care about the state of the heap in this context.  So we can actually recreate the exact same succession of 3N models.  Now, there is something interesting about this bootloader.  It is quite deterministic.  Without AS at all and with the fact that we are actually booting from more or less always the same state,  all the addresses, offsets, sizes that we find in the stack and in the heap will be the same every boot.  Which is why both functions will work in this case.  So, going back on what is going wrong in our exploits,  there is also the fact that the heap algorithm will write something at the address shelter plus 4.  This is because of the routine removing the check from the priest.  You can see here that we will dereference the thread pointer,  which is supposed to point to our shellcode and we will access the second pointer.  The system will override the second pointer, which is next, with something else.  So basically, we have the second value in our shellcode that is overwritten by the system.  There is an easy way to fix that.  We just need to skip the next instruction inside the shellcode.  If you are familiar with the Amazon, it looks like this.  So, we have the first node that will be skipped by the first instruction to happen on this program.  The final problem we have is that the heap after the exploits is in rematch with the priest.  So, it will crash after the next allocation or after the next boot.  There is no easy way to fix that.  We need to recreate the priest such that the heap is in a working state.  With all that being done, we have the same exploits that will work in the exact same way on both environments.  To sum up on this first vulnerability, we have the CD number you see here.  It leads to code execution in GitHub kernel and it is persistent.  It will survive reboots and factory resets because the partition containing the GPX will never be wiped.  Also, since GitHub kernel will load Android, so GitHub kernel is running in EL1,  but since it is loading Android, with a little amount of work,  we can bypass all the checks and take control over Android.  So, we will control the full number of objects in that part.  And it impacts at least all the Samsung devices we looked into that are based in MediaTek system on chips,  which includes those that are fixed in the boot run vulnerability.  Now, there is still one issue we have regarding the objecting,  which is to take control of the full system,  is that we need a way to flash this GPX on the device without being already privileged.  So, how to do this? This is the question we ask now and the one we try to answer.  For that, we will look into Odin, which is the recovery protocol designed by Samsung,  that is also implemented in GitHub kernel and it basically allows to flash partitions through USB.  We have a closed-source client that is called Sovodim,  that is the official one, let's say.  But there is also a low-cost one that is quite useful,  because it works very well on Linux, you can use it in common life,  it's angled and it's the one we use in our proof-of-concepts.  Internally, Odin works as the following.  So, first of all, all the images flashed to Odin must be authenticated.  They must contain a signature recruiter,  we have an example here of what the signature must look like.  Internally, there are two structures that Odin will use to do so.  The first one is the partition information table, that we'll call the bit,  and there is also a global array that indicates which partition to authenticate.  The partition information table is actually placed into a static address in the VMMC,  and it describes the partitions.  Each partition has an entry in the bit, you see an example on the right,  and it will give some information such as the size of the partition,  the name, where it starts, and so on.  And the partition that is not present in the bits cannot be flashed through Odin.  Although the bit can be updated, but as you can imagine, it requires a signed image.  Now, regarding authentication, we have this global array I mentioned,  and it will describe which partitions must be authenticated and how to authenticate them.  What is interesting, however, is that an image that is not part of this array  will not be authenticated, does not require authentication.  So if we compare the bits that give the list of all partitions that can be flashed,  and this array, indicating the one requiring authentication,  we end up with a list of partitions that we can flash without authentication.  Now, just a quick note on this list.  The up-param partition, the one containing the JPEG, is not part of them,  because it is authenticated.  But there are other interesting partitions that we can actually flash,  and two of them are eGPT and sGPT.  GPT stands for GeoID Partition Table.  So the GPT is similar to the bit in the sense that it describes the partitions.  You will find similar information, the names, the sizes, and so on.  And you can see that it's quite an interesting, quite a powerful primitive,  the fact that we can flash without authentication the headers of this GPT table.  It means that we can, through USB, reshape the GPT table.  Now, a few words about GPT versus bit.  As you know, as I explained, they are used for the same thing.  The bit is actually used for Samsung features, such as ODIN, such as JPEG loading.  So the up-param partition is actually retrieved through the bit and not through the GPT table.  And the GPT is used for the rest of the time, like for loading non-grid partitions, for example.  So when the system starts, it will execute this little routine you see in order to load the bit in memory.  So as I explained, we have this hard-coded address, which is where the system by default will read the bit from.  But there is also this interesting routine.  The system will try to look for a bit partition, and if there is one, it will read it from there.  So on all the devices we looked into, there was no such bit partition.  However, it's quite interesting because the code is there anyway, and these two functions rely on the GPT table.  And we can actually change this in this GPT table.  So we came up with a polling strategy.  Here is a representation of the flash memory.  You see the bit and GPT pointing to the same partitions.  And the first partition you see, mdflite-hdl, is actually one of those we can flash without authentication.  So we will replace this partition with a new apparam partition containing our managed-use GPT.  The second partition, dbmeta-bendo, isn't so flashable without authentication, and it's empty.  It seems not to be used, so we will replace it with a new bit, which is a copy of the original,  except that we will rename mdflite-hdl into apparam.  And we do the other way around with apparam.  And the final step is that we will modify the GPT table in order to rename dbmeta-bendo as a bit,  such that at the next boot, the system will not read the original bits, but will read the new one.  And whenever it will try to read GPT as a screen, it will look for the new apparam partition.  And it actually works.  You see on the screen dots showing up.  It means that the exposure worked.  So the GPEGs are loaded.  But we still have a little problem.  Unreal won't boot, and this is because the dbmeta-bendo partition is not present in the GPT table,  even though it's not really needed for anything.  So there is an easy way to overcome this problem.  We simply take another partition that seems to be useless, in this case the SP partition,  and we rename it to dbmeta-bendo.  And with that done, it actually works.  The device will boot and everything will be fine.  So to sum up on this second vulnerability,  we have an authentication bypass in Odin that we can use to flash more or less anything we want in the agency,  which includes the apparam partition.  And this vulnerability impacts most Samsung devices.  At least all of those we looked into.  That's all using MediaTek system issues.  Now before I get to the demo, a few words about post-exploitation,  because remember that our ultimate goal is to take control over the Android system,  and so far we are executing code in the Google kernel.  And the best way, the easiest way for us to control Android is to modify the partitions  that Daniel described at some point.  And the problem is that we have this ADB Unreal-Grid-fighting feature  that will complain if the partitions are different from the original ones.  So for that, we implemented a little routing in our shellcode  that will simply patch all the checks to basically not them.  And this is quite easy to do because the memory is already writable,  so code on the Google kernel is both executable and writable,  so no need to play with it.  I will call Daniel on stage to help me with the demo,  so there is a video in case it doesn't work, but I'm sure it will work.  Okay.  Okay, so we have to film actually the device.  I hope you can see the device. Okay.  So basically this is a normal device.  And let me first show you something.  Basically, obviously I enabled ADB for this demo,  and what I want to show you is that when I try to call SU,  which is used to get privileges on Android, it doesn't work,  which is the expected behavior for a normally standard Android device.  All right?  So far so good.  So what I will do now is simply shut down the device,  so like this.  So here I unlocked the device, but you can actually power off this device  by pressing all the buttons together for a couple of seconds.  Okay, then I will start it in the download mode,  so you can also do this without needing a privilege,  without having to edit the password.  So now I started the loading mode, and I will launch the exploit.  So basically the exploit will flash the partitions as I described it,  and here you should see the device rebooting,  because there is this little trick I'm not going to explain,  but basically we are flashing some Android partitions to take control over it.  And once it's done, the device will reboot,  and you should see Doge showing up, which means that the exploit worked.  Now we'll have to wait a bit for the device to take a bit of time to start,  so there are some Sumatois in the room.  Maybe this is one of the things that could be improved.  Okay, so I'll connect again to ADB, and we'll see as soon as it's working.  And we are good to start.  To conclude on the first part of this presentation,  we have a chain of two boxes,  which together leads to the execution of the kernel.  It's persistent.  It impacts many Samsung devices of the Galaxy family,  which is based on the Jetpack system and chips,  and we can trigger this through the USB  and take control over the full number as well, which includes Android.  But there are still some secrets in Android  that were stored and protected with the SQL block,  and they are still hidden from us.  So we wanted to show you something complete,  so Daniel will now show you how to decrypt these secrets.  Yes.  So, well, I mean, the talk could be over now, right?  We could all go for lunch and forget about this part.  But if you remember the system architecture from the slide I presented before,  there is this whole part of the system  that goes by the name of Secure World,  which we haven't touched yet,  and is, for the moment at least, still very secure.  We compromised everything that is in the bottom part,  so we took care of Android,  but we haven't touched anything on top of the drive.  So what we want to show for the next ten minutes or so  is that maybe secure is not the best word to describe this part of the world.  And to do so, we're going to start from the secure one.  So just to give you a little bit more context,  the secure monitor is the critical component  that makes sure there can be communication  between the non-secure world and the secure world.  So what happens?  Imagine that there is, at some point,  some application or some system service in the Android system  that wants to perform an operation that needs to happen in the secure world.  Well, there will be a chain of calls.  For example, it's an encryption with a key.  So you will have a chain of calls that end up in the HAL layer.  This, at some point, will also point out to a daemon  that will talk to the kernel,  and the kernel, at some point, will send an SMC,  which is a special instruction in ARM chips  that triggers an exception that will be handled by the DL3 monitor.  So the kernel triggers the SMC,  the monitor takes it,  and based on that, decides what to do.  Basically, either it solves whatever needs to be done internally in the monitor,  or it forwards the request to the deepest kernel,  which will probably, in turn, talk with the key master.  So, why do we want to look at the monitor?  Because that's the most critical component, right?  Whatever needs to go to the secure world passes through the monitor.  And also, because the code is pretty simple,  you have these handlers,  and these handlers are reachable from the kernel.  However, the code is, as I said, simple.  There's a lot of other interactions,  so fuzzing is not really feasible.  What we meant to do with this code was just static analysis.  So we talked about Tgress a little bit.  I'll go quickly over it, because we are actually running out of time.  But this is the OS for Tressall designed by Samsung.  It comes with different partitions that include different components  that magically come together.  If you want to learn more about it, actually,  we're not going to do much here.  But there are obviously very good references  from research that happened in the past,  for example, Rescure published a series of proposals  that were very interesting and useful.  So obviously, ATF is also a source, or at least this version.  So what we do is we take the image,  and we want to look for the part where there is a header  with a signature,  the very code starts where you see the MTKTB magic, in some sense.  And when you load it in your favorite disassembler,  the thing you want to look for is SMC headers.  So usually there's, well, in this case, there's two.  One is because there's two ways the communication can happen.  Either the header wants to talk to the secure board,  or the secure board wants to talk to the kernel.  The interesting one for us is the one exposed to the kernel.  And then you have these arguments that are literally the registers  that are set to be for encoding the SMC.  So we started looking at these SMC headers,  and we very quickly ended up on some interesting ones.  So this is the one corresponding to that SMC ID.  And as you can see, it almost feels like a read,  arbitrary read-read, right?  Because you have an argument that is fully controlled by the attacker,  fed into some array, and the header is returned.  But the argument isn't really ever checked.  Which means anyone can talk to this,  anyone that can talk to this SMC header  can essentially read the subheader in the SMC,  in the ATX memory.  So this means we have an interesting read primitive  that, however, only gives us access to the memory  of the other space of the monitor.  Which is still pretty interesting,  but it can't really give us much,  because of other software.  Because the interesting secrets actually  lay in the trusted applications, usually.  So it would be actually nice if we could map the secrets we wanted  right into the other space of DTF.  Well, it turns out that  there is actually a way to do that,  and it's actually not so complicated.  There is another SMC header  that corresponds to the ID you see on the slides now.  Here, SPM actions is, again, after your name.  It's the one we gave while doing reverse engineering.  But we guess it has something to do with power management.  And what happens is that  you can pass an address  and a size to this function  that comes from the arguments,  and basically go over every value.  So you can tell the monitor,  please map in your other space  from this address, this size.  And these arguments are actually the same.  So we get to another vulnerability,  which perhaps by itself is not extremely serious,  because you just map memory.  But given the fact that we have the previous vulnerability,  if we combine them,  it means that we can map arbitrary memory  from the secure world,  and then read it back.  The only limit is that we are limited to 8 megabytes.  Then, since we cannot unmap,  the system will start to be quite unstable.  But that's not a big deal.  That's still a lot of space,  a lot of stuff that we can do.  And actually, we can use this vulnerability  to end up leaking a key store of keys,  which is kind of the ultimate level  of things that you want to leak.  I will be quick, I swear.  There is three professional databases  that have 400 keys, essentially.  You can have software keys,  TEE protected keys,  which is the case we are going to describe now,  and then strongbox protected keys,  which are keys that will end up being used  in security chips for the phones that have them.  The idea is that the raw key material  should never be the protected environment  in the longest.  So the way it happens actually in practice  is that the normal world,  as we saw before,  at some point we want to perform  some operation with the key.  So the key is actually stored in the file system  in a printed form.  So it will send this key  to the environment of choice,  either the keymaster trusted application  or the trusted chip,  again, when the phone has one.  And this thing will take the key  out of this blob  using some secrets that are internal  to the TA of the chip,  use the key,  and then return the result of the operation  without ever revealing that key.  So the content of the key  is what we want to leak.  And how can we do that?  Again, we described the bugs before  and we want to look for the keymaster memory.  So we're going to ask,  where is the keymaster memory?  We have some logs that are easily available.  These are little kernel logs.  We know it says k-message  where k is little kernel in this case.  Or at least it's very good  if the little kernel messages end up here.  And we have some physical addresses  that are expressed here.  There's one that looks pretty interesting.  It says TEE reserve.  And when it turns out that  that's where keymaster  and the other trusted applications  are loaded in memory.  You can tell that because of the many strings  that the trusted applications have.  And again, the binaries are stored in memory,  so you can pretty much compare these strings  and make sure that you're looking at the right thing.  So at this point, our bug becomes  more or less clear, I guess.  We import a key into the Android Keystore.  We encrypt using that key.  But we stop the execution  right after we begin operations.  So in a moment where the key will be present  in plain text in the memory of the keymaster TA.  And then we need it.  So translated to code,  this is something like this.  We are importing, actually, a key that we already know.  And we will explain later why.  But obviously, any key can be used.  So going over the same schema again,  we cook the keymaster HAL  to intercept the execution  right at the moment where we can be.  And then, when we actually do the leak,  we see the key appearing  in the buffer that we read.  But yeah, so again, we are leaking a key we already knew.  So we could do better than this.  But again, this is really just for practicality.  The thing is that you see around,  there's a bunch of almost random things.  We could figure out the right offsets,  but maybe they change.  Who knows? It's easier to enforce.  At the end of the day, there are not that many options.  So we can try all possible keys  from the leak to the cipher,  the ciphertext that we actually have.  And we will be able to actually find the key  even if we didn't know.  So to show you this, we have another decoder  for which I'm going to need Max again.  So no need for the camera this time,  because we...  So we prepared a little demo application  which is going to appear on the screen soon,  which essentially does what you have seen from before.  So I'm going to wait for Max to launch the script  that will give us...  that will use Frida to intercept the messages  that we care about.  So here now he's launching the Frida server.  By the way, Frida is a common instrumentation framework  that I haven't introduced because  many people know about it.  But if you don't, have a look. It's really cool.  So when you look at the logs,  just because you are going to be logging  some, like the ciphertext,  just to make it easier to watch.  And can I...  So I'm going to write my dirty secret here.  Encrypt.  And here in the logs, if stuff is working...  Yes.  You're going to be able to see  the ciphertext and the initialization vector.  Now once we have done that,  we can use the script I explained about.  Actually, I haven't fully explained how to do it  because we have to be in the kernel, right?  So we wrote the custom kernel module  that will be able to send the SMC code.  We haven't gone over that part  because it's maybe the least interesting.  But anyway, we end up leaking some memory  out of the ATF address space,  which is stored in the sub-graphical file system.  So now Max is pulling it from...  the...  in this file system,  and then we launch a script  that will try all the possibilities in this link  to find the secret  using the ciphertext and ID that we...  that we got.  So yeah, that's just a little bit of Base64 magic.  A bit of pressure on Max  that missed the typo in this.  Maybe you can raise the sign with the time again.  Out of time.  All right.  And then...  Fingers crossed.  The terminalism is helpful once again.  So yeah, the key is...  I mean, we can show you the sources  if they weren't super dirty,  but I'm sure you can trust that we are not.  All right.  So let me go back to the presentation.  Yes.  So, to wrap up,  we presented a total of four vulnerabilities today  that led to bypassing the authentication  that happens in Odin.  And this allowed us to flash an image  that was malicious  and that will be able to execute the vulnerability  in the parsing logic on the meter kernel.  This gave us code execution in the book loader  and then allowed us to  shield backdoor algorithm.  And then using two other bugs in the secure world,  we need some memory  including keys that are supposed to be protected.  So all these vulnerabilities  have been found in low-end Samsung devices.  And as you can see,  they're relatively simple at the end of the day  but very impactful  also due to the lack of mitigations that we found  in the various components that we exploited.  So this kind of shows how challenging it is  to manufacture these devices  and maintain security features  especially when they're very good  but at the same time it's also unfortunate  because they were relatively low-end devices.  But anyway, all the vulnerabilities are now fixed  and we also thank Samsung that was super reactive  making sure that these get patches.  And with that, we are done.


url: https://www.youtube.com/watch?v=Nxy6SIM11sA
title: Life is a Video Game, These Are the Cheat Codes
type: video
author: Mark Manson
ingestion_date: 2024-09-03
transcription_model: large-v2
content:
  {
    "webpage_url": "https://www.youtube.com/watch?v=Nxy6SIM11sA",
    "title": "Life is a Video Game, These Are the Cheat Codes",
    "description": "This video was sponsored by BetterHelp.\n\nGet 10% off BetterHelp by signing up via my link: https://www.betterhelp.com/markmanson\n\nJoin me as I level through the video game of life. From character progression to choosing allies, by the end of this video I'll give you all the cheat codes to level up faster. \n\nFor useful practical advice each week, sign up for my free newsletter: https://mrk.mn/4d2W633\n\nIf you are not already a member of my premium membership, get access to my courses and exclusive writing here: http://bit.ly/3LwHWfi\n\nI am Mark Manson, 3x #1 NY Times bestselling author of:\n\nThe Subtle Art of Not Giving a Fck - https://mrk.mn/3svfxcu\nEverything Is Fcked: A Book About Hope - https://mrk.mn/2RNxVAD\n\nI share other types of content to make you a less awful human in these places:\n\nhttps://markmanson.net/\nhttps://instagram.com/markmanson/\nhttps://twitter.com/IAmMarkManson\nhttps://facebook.com/Markmansonnet/\nhttps://linkedin.com/in/markmanson/\nhttps://www.tiktok.com/@iammarkmanson\n\n#sponsored \n\nIf you have any questions about the brand relating to how the therapists are licensed, their privacy policy, or therapist compensation model, check out this FAQ: https://www.betterhelp.com/your-questions-answered/",
    "channel_url": "https://www.youtube.com/channel/UC0TnW9acNxqeojxXDMbohcA",
    "duration": 759,
    "channel": "Mark Manson",
    "uploader": "Mark Manson",
    "upload_date": "20240825"
  }

  This text was transcribed using whisper model: large-v2

   Have you ever gotten completely lost in a video game and wondered,  why can't I have this sort of focus and dedication in my actual life?  That's because in life you don't understand the game you are playing.  In this video, I'm going to lay out in painfully simple terms  exactly what the game of life entails, how it is played  and why you have failed to advance as far as you would like.  And of course, I will give you the cheat codes so that you can warp further ahead.  Let's get into it.  Now, video games are something known as finite games.  They have a strict set of conditions that once met, the game is over.  You beat the dragon and save the princess and you win.  You beat up the bad guy and save the world and you win.  You fucking destroy whatever that thing is.  I guess you win.  But life is what's called an infinite game.  And the goal of an infinite game is to keep playing as long as possible.  This has a series of counterintuitive consequences  that mean you have to approach the game differently.  You don't necessarily always want to beat the bad guy and save the princess,  because that would mean you no longer have some goal by which to improve yourself.  That is, it's no longer clear and obvious how to continue the game.  I'm fine. OK, we're fine, aren't we?  We're good here, mate.  This is what's called an existential crisis.  And don't worry, we'll come back to it.  Most video games are designed so that there are a series of levels  and each time you advance from one level to the next,  you gain a special skill or ability or knowledge  that will help you improve and conquer the next levels.  So in video games, victories will make your character stronger  and defeat will cause you to remain the same.  But in the game of life, it is your failures  that make your character stronger and successes that cause you to stay the same.  Therefore, paradoxically, the point of the game of life  is not necessarily to win at everything you do,  but rather to continuously build your character through failures  and setbacks in as many useful ways as possible.  But don't worry, as long as you are active and engaged with the world,  this is not difficult.  As an infinite game, life has an infinite number of ways  to kick you in the balls and make you feel like a failure.  The question is how you choose to handle those failures once they come,  because handling failures in life is completely different than video games  as well. In a video game, if you fuck up a mission, you get to retry  that mission a thousand times until you get it right.  But in life, if you fuck up a relationship, the only way to get it right  is to get it right in the next relationship.  Video games give you the quests and you get to design the character.  But in real life, you were given the character and you have to design the quest.  Again, video games have clear conditions which you have to meet to win.  Most games lay these conditions out in excruciating detail,  going as far as walking you through every tiny thing you need to do to be a winner.  The fun, then, is in designing or adapting or choosing your character  to accomplish these quests.  Do you want to be a lawless barbarian or do you want to be a noble sorcerer?  Do you want to just break a bunch of shit?  In the game of life, there are infinite quests,  yet you are limited in your abilities and knowledge.  Therefore, the goal is to find and choose the best quest to suit your character,  to allow you to play the game as long and meaningfully as possible.  And this brings us to our first cheat code.  In video games,  you generally want to rack up as many side quests as possible  to level up your character and get sick loot.  But in the game of life, side quests are a fun distraction at best  and waste years of your life at worst.  In this day and age, it is incredibly easy to get sidetracked  onto a bunch of useless side quests and vanity tasks  that have no actual impact on the quality of your life.  A huge hack to winning the game of life, then, is to simply be more focused  and obsessed about your main quest than other people.  So the fewer side quests, the better.  In video games, side quests tend to be kind of lame  and little more than glorified errands.  But in real life, the side quests are generally sexy, exciting and seductive.  Now, this is going to be incredibly difficult to forego.  But the more you can give up the dumb side quests,  the more you'll stay on track with your main quest,  leading to a happier and more fulfilling life.  It's not easy. It's not fun.  But, you know, that's the whole thing about being a hero.  You have to give up stuff.  In video games, you know who your character is  from the first moment you start the game.  You know how well you can run, jump, pick up things or shoot a gun.  In some cases, you even get to pick who your character is  and all the traits that they have.  You can be like a badass night elf with gigantic.  Well, anyway, the game of life is weird because for the first few decades,  you don't actually know who your character is.  You don't know what you're good at.  You don't know what your talents are.  You don't know what you're going to enjoy pursuing  or how you're going to respond to adversity.  Therefore, the first goal of every new character in life  is to simply gain self-knowledge.  Figure out who the fuck you are and what you seem to be inclined to do.  This means lots of experimenting.  Go out and try some simple quest lines and see how far you can get.  Join the debate club.  Oh, wait, you hate speaking in front of people, have social anxiety.  All right. Maybe do like the math Olympiad or something.  Oh, wait, you're terrible at math.  OK, well, maybe try solving a Rubik's Cube blindfolded.  You suck at that, too.  OK, well, like maybe become this kid.  Boom. Now you're a hero.  I learned at a young age that I was terrible at sports.  But I also learned that I was highly creative.  Now, I got pushed into a lot of lockers and had my sexuality questioned  by mouth breathers with the IQ of a T-Rex.  But today that adversity has merely helped me.  I'm able to create things, put them out into the world  and not give a fuck if morons don't like them.  The process of getting to know your character over time  will continue throughout your life.  But the bulk of that realization should happen while you're still young.  If you're struggling to understand your own character  and what quests will actually make your life meaningful,  then therapy can be one of the most useful cheat codes  to get ahead on this process.  And that also brings us to the sponsor of today's video, BetterHelp.  BetterHelp is like the video game version of therapy.  You can log in at any time and access your therapist remotely over text  or even through a Zoom call.  Your therapist is kind of like Cortana and Halo or Chadley from Final Fantasy  Seven, always up in your business, pointing out when you're  bullshitting yourself or fucking up your quest lines.  The best thing, though, is that with BetterHelp, you can always switch  therapists. You can do so at any time and there's no questions asked.  I would have given anything to get rid of that nosy prick, Chadley.  But alas, Cloud was too cheap to pay for a real therapist.  I'm just here for the paycheck.  Use the link in the description below to get 10% off your first month  or go to betterhelp.com slash Mark Manson and get started  learning about your character today.  Choosing the right quest is arguably the biggest  and most difficult component of winning the game of life.  Strong quests reveal character and build skills.  A quest to live abroad for a year is great because it will teach you  many things about yourself and you can develop communication skills,  relationship skills, self-confidence, independence, all that good shit.  Bad quests, though, obscure your character and waste skills.  An example of a bad quest is like drinking all 268 beers on tap  at the lager house near your old university.  It blinds you to your own character and waste precious time, energy and mana.  Another bad quest is only trying to own a fancy car.  Not only does this quest not build many skills, but it's likely motivated  by hiding who you are from the world, not revealing it.  And actually, this is kind of the biggest mistake  that people make when choosing quests.  They mistake someone else's quest line for their own.  You owning a Lamborghini is likely not your own quest line.  It's the quest line of the marketers working at Lamborghini  or some douchey YouTuber who wants you to envy their quest line.  Many times in life, people will try to impose their quest lines on you  in hopes that you will complete it for them.  This could be your parents wanting you to go to a certain type of school  or a partner who wants you to fix their emotional problems  or a company who's just marketing their useless shit to you.  Do not be seduced by other people's quest lines.  It's easy to give in and try to chase other people's dreams  because it relieves you of the responsibility of choosing your own.  Now, boundaries sound like a wishy washy term  that your Aunt Margaret says before giving you a tarot card reading,  but boundaries are actually an incredibly practical  and important relationship tool that I would argue everybody should know and learn.  Now, the core of boundaries is simple.  You cannot complete other people's quests for them,  and no one else can complete your quest for you.  And if people try to complete yours or if they ask you to complete theirs,  it's your responsibility to tell them to fuck off.  No, you should learn the meaning of the word.  If you don't tell them no, not only will you waste your precious time and energy,  but you will prevent them from advancing in their own quests,  thus wasting theirs as well.  Now, here's a harsh truth.  Once selected, your ability to advance in your quest will come down to three things.  Your character traits, your ability to focus,  and your ability to stomach failure and setback.  Your character traits are a given.  It's your job to discover them and then leverage them.  We've already talked about that.  Your focus is based on your ability to turn down useless  but exciting side quests and enforce boundaries.  The progress is really going to be proportional to your ability to stomach failure.  Unlike video games, in the game of life,  setbacks and failures are what make your character stronger.  Put another way, grinding levels in a video game  means winning tons of easy battles over and over to gain experience,  but grinding levels in real life means losing hard battles to gain experience.  That's why...  Most people hate failure because they feel judged or embarrassed in front of others.  If you feel this way, it's probably because you do not understand your character enough  or you're living too much on other people's quest lines, not your own.  As a result, most people develop an aversion to failure.  They would rather spend their lives whittling time away on small, meaningless quests  that prop up the delusions of their character  rather than risk failure at a big, meaningful quest.  But if you can learn to enjoy failure,  if you can learn to enjoy the feeling of trying something,  having it not work, and then learning what to do instead,  you will become unstoppable.  You will progress further and faster than anyone else,  and you will truly accomplish great feats like a true level 99 hero.  This is where the power lies!  All right, get ready!  There's a final boss in a classic video game named Mike Tyson,  who once said,  not everyone who hurts you is an enemy,  and not everyone who helps you is a friend.  It's important to realize that while on your quest,  there will be many people who naturally align with your quest  and many who do not.  This is inevitable.  The challenge in the game of life is less about avoiding enemies  than simply recognizing who and what they are.  Enemies are people who would try to divert you from completing your quest.  Some enemies do this because their quests and yours contradict one another.  But most enemies do it simply because they envy the progress that you've made  or that you could potentially make.  They falsely believe that you progressing in your quest  somehow diminishes the progress that they've made in theirs.  This is the envy trap.  When we see others advancing far in their quest lines,  it sometimes makes us feel inadequate in our own.  But this actually makes no sense.  We are different characters.  We usually have no idea the sacrifices  that other people have made in their quests.  It's important to simply stay focused on your own.  You don't know what people gave up for their successes.  Therefore, it's impossible to truly envy what they have.  Put another way, you cannot envy the benefits of someone's life  without also envying the costs.  And finally, there will be people  who will naturally align their quest with yours.  These are special people,  and you should take great care of them when you come across them.  Not only because they will aid you on your quest,  but because all of the cliches are true.  Victory is really only worth experiencing when it's shared.  It's counterintuitive, but helping other people with their quest  will make it easier to advance in yours.  This is because you will build alliances  and goodwill towards your goals.  People will share information, knowledge, and skills with you.  They will help protect you from diversions  and lame side quests,  and they will have your best interests at heart.  And other times, they'll just love you.  Basically, the more you try to help other people win,  the more they'll try to help you win.  This is the opposite of the envy trap.  Let's call it the charity cheat code.  Nothing gets you further ahead  than giving away progress to others.  This is a weird loophole in the game of life.  The grand illusion that we all seem to fall for  time and time again,  that we mistakenly believe that we must be the hero  and the world should be our sidekick,  when actually, the opposite is true.  There is no hero, and we're all each other's sidekicks.  Thanks for being my sidekick.  I could actually use some fucking help.  No, no, no, no, no, no, no, no, no, fuck!  God, I fucking dodged.  I fucking dodged.  That's bullshit.  Ow.


