CINXE.COM

Project Zero: June 2022

<!DOCTYPE html> <html class='v2' dir='ltr' lang='en' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <meta content='width=1100' name='viewport'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='https://googleprojectzero.blogspot.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='https://googleprojectzero.blogspot.com/2022/06/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Project Zero - Atom" href="https://googleprojectzero.blogspot.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Project Zero - RSS" href="https://googleprojectzero.blogspot.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Project Zero - Atom" href="https://www.blogger.com/feeds/4838136820032157985/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='https://googleprojectzero.blogspot.com/2022/06/' property='og:url'/> <meta content='Project Zero' property='og:title'/> <meta content='News and updates from the Project Zero team at Google' property='og:description'/> <title>Project Zero: June 2022</title> <style type='text/css'>@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;font-stretch:normal;font-display:swap;src:url(//fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0B4gaVY.eot);}</style> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Simple Designer: Blogger URL: www.blogger.com ----------------------------------------------- */ /* Variable definitions ==================== <Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/> <Group description="Page Text" selector="body"> <Variable name="body.font" description="Font" type="font" default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="body.text.color" description="Text Color" type="color" default="#222222"/> </Group> <Group description="Backgrounds" selector=".body-fauxcolumns-outer"> <Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/> <Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/> <Variable name="header.background.color" description="Header Background" type="color" default="transparent"/> </Group> <Group description="Links" selector=".main-outer"> <Variable name="link.color" description="Link Color" type="color" default="#2288bb"/> <Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/> <Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/> </Group> <Group description="Blog Title" selector=".header h1"> <Variable name="header.font" description="Font" type="font" default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" /> </Group> <Group description="Blog Description" selector=".header .description"> <Variable name="description.text.color" description="Description Color" type="color" default="#777777" /> </Group> <Group description="Tabs Text" selector=".tabs-inner .widget li a"> <Variable name="tabs.font" description="Font" type="font" default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/> <Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/> </Group> <Group description="Tabs Background" selector=".tabs-outer .PageList"> <Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/> <Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/> </Group> <Group description="Post Title" selector="h3.post-title, .comments h4"> <Variable name="post.title.font" description="Font" type="font" default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> </Group> <Group description="Date Header" selector=".date-header"> <Variable name="date.header.color" description="Text Color" type="color" default="#000000"/> <Variable name="date.header.background.color" description="Background Color" type="color" default="transparent"/> <Variable name="date.header.font" description="Text Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/> <Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/> <Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/> </Group> <Group description="Post Footer" selector=".post-footer"> <Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/> <Variable name="post.footer.background.color" description="Background Color" type="color" default="#f9f9f9"/> <Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/> </Group> <Group description="Gadgets" selector="h2"> <Variable name="widget.title.font" description="Title Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/> <Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/> </Group> <Group description="Images" selector=".main-inner"> <Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/> <Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/> <Variable name="image.text.color" description="Caption Text Color" type="color" default="#000000"/> </Group> <Group description="Accents" selector=".content-inner"> <Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/> <Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="transparent"/> </Group> <Variable name="body.background" description="Body Background" type="background" color="#eeeeee" default="$(color) none repeat scroll top left"/> <Variable name="body.background.override" description="Body Background Override" type="string" default=""/> <Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/body_gradient_tile_light.png)"/> <Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/> <Variable name="content.padding" description="Content Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px" min="0" max="100px"/> <Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px" min="0" max="100px"/> <Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px" min="0" max="100px"/> <Variable name="main.border.width" description="Main Border Width" type="length" default="0" min="0" max="10px"/> <Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/> <Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px" min="0" max="100px"/> <Variable name="header.padding" description="Header Padding" type="length" default="30px" min="0" max="100px"/> <Variable name="header.border.size" description="Header Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/> <Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" min="0" max="100px"/> <Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" min="0" max="100px"/> <Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px" min="0" max="100px"/> <Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px" min="0" max="10px"/> <Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px" min="0" max="10px"/> <Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/> <Variable name="page.width" description="Page Width" type="string" default="auto"/> <Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding" description="Main Padding" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px" min="0" max="100px"/> <Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px" min="0" max="100px"/> <Variable name="paging.background" color="#ffffff" description="Background of blog paging area" type="background" default="transparent none no-repeat scroll top center"/> <Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0" min="0" max="10px"/> <Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string" default="transparent none repeat scroll top left"/> <Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/> <Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" /> <Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/> <Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/> */ /* Content ----------------------------------------------- */ body { font: normal normal 12px Open Sans; color: #000000; background: #eeeeee none repeat scroll top left; padding: 0 0 0 0; } html body .region-inner { min-width: 0; max-width: 100%; width: auto; } h2 { font-size: 22px; } a:link { text-decoration:none; color: #2288bb; } a:visited { text-decoration:none; color: #888888; } a:hover { text-decoration:underline; color: #33aaff; } .body-fauxcolumn-outer .fauxcolumn-inner { background: transparent none repeat scroll top left; _background-image: none; } .body-fauxcolumn-outer .cap-top { position: absolute; z-index: 1; height: 400px; width: 100%; } .body-fauxcolumn-outer .cap-top .cap-left { width: 100%; background: transparent none repeat-x scroll top left; _background-image: none; } .content-outer { -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .15); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .15); -goog-ms-box-shadow: 0 0 0 #333333; box-shadow: 0 0 0 rgba(0, 0, 0, .15); margin-bottom: 1px; } .content-inner { padding: 10px 40px; } .content-inner { background-color: #ffffff; } /* Header ----------------------------------------------- */ .header-outer { background: transparent none repeat-x scroll 0 -400px; _background-image: none; } .Header h1 { font: normal normal 40px Open Sans; color: #000000; text-shadow: 0 0 0 rgba(0, 0, 0, .2); } .Header h1 a { color: #000000; } .Header .description { font-size: 18px; color: #000000; } .header-inner .Header .titlewrapper { padding: 22px 0; } .header-inner .Header .descriptionwrapper { padding: 0 0; } /* Tabs ----------------------------------------------- */ .tabs-inner .section:first-child { border-top: 0 solid #dddddd; } .tabs-inner .section:first-child ul { margin-top: -1px; border-top: 1px solid #dddddd; border-left: 1px solid #dddddd; border-right: 1px solid #dddddd; } .tabs-inner .widget ul { background: transparent none repeat-x scroll 0 -800px; _background-image: none; border-bottom: 1px solid #dddddd; margin-top: 0; margin-left: -30px; margin-right: -30px; } .tabs-inner .widget li a { display: inline-block; padding: .6em 1em; font: normal normal 12px Open Sans; color: #000000; border-left: 1px solid #ffffff; border-right: 1px solid #dddddd; } .tabs-inner .widget li:first-child a { border-left: none; } .tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover { color: #000000; background-color: #eeeeee; text-decoration: none; } /* Columns ----------------------------------------------- */ .main-outer { border-top: 0 solid transparent; } .fauxcolumn-left-outer .fauxcolumn-inner { border-right: 1px solid transparent; } .fauxcolumn-right-outer .fauxcolumn-inner { border-left: 1px solid transparent; } /* Headings ----------------------------------------------- */ div.widget > h2, div.widget h2.title { margin: 0 0 1em 0; font: normal bold 11px 'Trebuchet MS',Trebuchet,Verdana,sans-serif; color: #000000; } /* Widgets ----------------------------------------------- */ .widget .zippy { color: #999999; text-shadow: 2px 2px 1px rgba(0, 0, 0, .1); } .widget .popular-posts ul { list-style: none; } /* Posts ----------------------------------------------- */ h2.date-header { font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; } .date-header span { background-color: #bbbbbb; color: #ffffff; padding: 0.4em; letter-spacing: 3px; margin: inherit; } .main-inner { padding-top: 35px; padding-bottom: 65px; } .main-inner .column-center-inner { padding: 0 0; } .main-inner .column-center-inner .section { margin: 0 1em; } .post { margin: 0 0 45px 0; } h3.post-title, .comments h4 { font: normal normal 22px Open Sans; margin: .75em 0 0; } .post-body { font-size: 110%; line-height: 1.4; position: relative; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 2px; background: #ffffff; border: 1px solid #eeeeee; -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body .tr-caption-container { color: #666666; } .post-body .tr-caption-container img { padding: 0; background: transparent; border: none; -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1); box-shadow: 0 0 0 rgba(0, 0, 0, .1); } .post-header { margin: 0 0 1.5em; line-height: 1.6; font-size: 90%; } .post-footer { margin: 20px -2px 0; padding: 5px 10px; color: #666666; background-color: #eeeeee; border-bottom: 1px solid #eeeeee; line-height: 1.6; font-size: 90%; } #comments .comment-author { padding-top: 1.5em; border-top: 1px solid transparent; background-position: 0 1.5em; } #comments .comment-author:first-child { padding-top: 0; border-top: none; } .avatar-image-container { margin: .2em 0 0; } #comments .avatar-image-container img { border: 1px solid #eeeeee; } /* Comments ----------------------------------------------- */ .comments .comments-content .icon.blog-author { background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9sLFwMeCjjhcOMAAAD+SURBVDjLtZSvTgNBEIe/WRRnm3U8RC1neQdsm1zSBIU9VVF1FkUguQQsD9ITmD7ECZIJSE4OZo9stoVjC/zc7ky+zH9hXwVwDpTAWWLrgS3QAe8AZgaAJI5zYAmc8r0G4AHYHQKVwII8PZrZFsBFkeRCABYiMh9BRUhnSkPTNCtVXYXURi1FpBDgArj8QU1eVXUzfnjv7yP7kwu1mYrkWlU33vs1QNu2qU8pwN0UpKoqokjWwCztrMuBhEhmh8bD5UDqur75asbcX0BGUB9/HAMB+r32hznJgXy2v0sGLBcyAJ1EK3LFcbo1s91JeLwAbwGYu7TP/3ZGfnXYPgAVNngtqatUNgAAAABJRU5ErkJggg==); } .comments .comments-content .loadmore a { border-top: 1px solid #999999; border-bottom: 1px solid #999999; } .comments .comment-thread.inline-thread { background-color: #eeeeee; } .comments .continue { border-top: 2px solid #999999; } /* Accents ---------------------------------------------- */ .section-columns td.columns-cell { border-left: 1px solid transparent; } .blog-pager { background: transparent url(//www.blogblog.com/1kt/simple/paging_dot.png) repeat-x scroll top center; } .blog-pager-older-link, .home-link, .blog-pager-newer-link { background-color: #ffffff; padding: 5px; } .footer-outer { border-top: 1px dashed #bbbbbb; } /* Mobile ----------------------------------------------- */ body.mobile { background-size: auto; } .mobile .body-fauxcolumn-outer { background: transparent none repeat scroll top left; } .mobile .body-fauxcolumn-outer .cap-top { background-size: 100% auto; } .mobile .content-outer { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15); box-shadow: 0 0 3px rgba(0, 0, 0, .15); } .mobile .tabs-inner .widget ul { margin-left: 0; margin-right: 0; } .mobile .post { margin: 0; } .mobile .main-inner .column-center-inner .section { margin: 0; } .mobile .date-header span { padding: 0.1em 10px; margin: 0 -10px; } .mobile h3.post-title { margin: 0; } .mobile .blog-pager { background: transparent none no-repeat scroll top center; } .mobile .footer-outer { border-top: none; } .mobile .main-inner, .mobile .footer-inner { background-color: #ffffff; } .mobile-index-contents { color: #000000; } .mobile-link-button { background-color: #2288bb; } .mobile-link-button a:link, .mobile-link-button a:visited { color: #ffffff; } .mobile .tabs-inner .section:first-child { border-top: none; } .mobile .tabs-inner .PageList .widget-content { background-color: #eeeeee; color: #000000; border-top: 1px solid #dddddd; border-bottom: 1px solid #dddddd; } .mobile .tabs-inner .PageList .widget-content .pagelist-arrow { border-left: 1px solid #dddddd; } --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 1120px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 1120px; max-width: 1120px; _width: 1120px; } .main-inner .columns { padding-left: 0; padding-right: 310px; } .main-inner .fauxcolumn-center-outer { left: 0; right: 310px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0") - parseInt("310px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0; } .main-inner .fauxcolumn-right-outer { width: 310px; } .main-inner .column-left-outer { width: 0; right: 100%; margin-left: -0; } .main-inner .column-right-outer { width: 310px; margin-right: -310px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } body#layout div.add_widget { padding: 8px; } body#layout div.add_widget a { margin-left: 32px; } --></style> <script type='text/javascript'> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-240546891-1', 'auto', 'blogger'); ga('blogger.send', 'pageview'); </script> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=4838136820032157985&amp;zx=9e014bfb-e50c-4ece-bb2f-ed942adb173a' media='none' onload='if(media!=&#39;all&#39;)media=&#39;all&#39;' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=4838136820032157985&amp;zx=9e014bfb-e50c-4ece-bb2f-ed942adb173a' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body class='loading'> <div class='navbar section' id='navbar' name='Navbar'><div class='widget Navbar' data-version='1' id='Navbar1'><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar/4838136820032157985?origin\x3dhttps://googleprojectzero.blogspot.com', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script><script type="text/javascript"> (function() { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '//pagead2.googlesyndication.com/pagead/js/google_top_exp.js'; var head = document.getElementsByTagName('head')[0]; if (head) { head.appendChild(script); }})(); </script> </div></div> <div class='body-fauxcolumns'> <div class='fauxcolumn-outer body-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content'> <div class='content-fauxcolumns'> <div class='fauxcolumn-outer content-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content-outer'> <div class='content-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left content-fauxborder-left'> <div class='fauxborder-right content-fauxborder-right'></div> <div class='content-inner'> <header> <div class='header-outer'> <div class='header-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left header-fauxborder-left'> <div class='fauxborder-right header-fauxborder-right'></div> <div class='region-inner header-inner'> <div class='header section' id='header' name='Header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner'> <div class='titlewrapper'> <h1 class='title'> <a href='https://googleprojectzero.blogspot.com/'> Project Zero </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>News and updates from the Project Zero team at Google</span></p> </div> </div> </div></div> </div> </div> <div class='header-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </header> <div class='tabs-outer'> <div class='tabs-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left tabs-fauxborder-left'> <div class='fauxborder-right tabs-fauxborder-right'></div> <div class='region-inner tabs-inner'> <div class='tabs no-items section' id='crosscol' name='Cross-Column'></div> <div class='tabs no-items section' id='crosscol-overflow' name='Cross-Column 2'></div> </div> </div> <div class='tabs-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='main-outer'> <div class='main-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left main-fauxborder-left'> <div class='fauxborder-right main-fauxborder-right'></div> <div class='region-inner main-inner'> <div class='columns fauxcolumns'> <div class='fauxcolumn-outer fauxcolumn-center-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-left-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-right-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <!-- corrects IE6 width calculation --> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='main section' id='main' name='Main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <h2 class='date-header'><span>Thursday, June 30, 2022</span></h2> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='4838136820032157985' itemprop='blogId'/> <meta content='256978548158816980' itemprop='postId'/> <a name='256978548158816980'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://googleprojectzero.blogspot.com/2022/06/2022-0-day-in-wild-exploitationso-far.html'>2022 0-day In-the-Wild Exploitation&#8230;so far</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-256978548158816980' itemprop='description articleBody'> <style type="text/css">ul.lst-kix_68660h7uawx-0{list-style-type:none}ul.lst-kix_68660h7uawx-1{list-style-type:none}ul.lst-kix_68660h7uawx-2{list-style-type:none}ul.lst-kix_68660h7uawx-3{list-style-type:none}ul.lst-kix_68660h7uawx-4{list-style-type:none}ul.lst-kix_68660h7uawx-5{list-style-type:none}ul.lst-kix_68660h7uawx-6{list-style-type:none}.lst-kix_68660h7uawx-7>li:before{content:"\0025cb "}ul.lst-kix_68660h7uawx-7{list-style-type:none}ul.lst-kix_68660h7uawx-8{list-style-type:none}.lst-kix_68660h7uawx-0>li:before{content:"\0025cf "}.lst-kix_68660h7uawx-6>li:before{content:"\0025cf "}.lst-kix_68660h7uawx-8>li:before{content:"\0025a0 "}li.li-bullet-0:before{margin-left:-18pt;white-space:nowrap;display:inline-block;min-width:18pt}.lst-kix_68660h7uawx-3>li:before{content:"\0025cf "}.lst-kix_68660h7uawx-2>li:before{content:"\0025a0 "}.lst-kix_68660h7uawx-4>li:before{content:"\0025cb "}.lst-kix_68660h7uawx-1>li:before{content:"\0025cb "}.lst-kix_68660h7uawx-5>li:before{content:"\0025a0 "}ol{margin:0;padding:0}table td,table th{padding:0}.HZWKYxoXby-c2{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:156.8pt;border-top-color:#000000;border-bottom-style:solid}.HZWKYxoXby-c9{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:155.2pt;border-top-color:#000000;border-bottom-style:solid}.HZWKYxoXby-c3{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:156pt;border-top-color:#000000;border-bottom-style:solid}.HZWKYxoXby-c19{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:8pt;font-family:"Arial";font-style:normal}.HZWKYxoXby-c15{color:#000000;font-weight:700;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.HZWKYxoXby-c5{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.HZWKYxoXby-c4{padding-top:0pt;padding-bottom:0pt;line-height:1.5;orphans:2;widows:2;text-align:left;height:11pt}.HZWKYxoXby-c6{padding-top:0pt;padding-bottom:0pt;line-height:1.5;orphans:2;widows:2;text-align:left}.HZWKYxoXby-c12{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial"}.HZWKYxoXby-c17{border-spacing:0;border-collapse:collapse;margin-right:auto}.HZWKYxoXby-c0{padding-top:0pt;padding-bottom:0pt;line-height:1.0;text-align:left}.HZWKYxoXby-c1{text-decoration-skip-ink:none;-webkit-text-decoration-skip:none;color:#1155cc;text-decoration:underline}.HZWKYxoXby-c14{background-color:#ffffff;max-width:468pt;padding:72pt 72pt 72pt 72pt}.HZWKYxoXby-c18{margin-left:36pt;padding-left:0pt}.HZWKYxoXby-c8{color:inherit;text-decoration:inherit}.HZWKYxoXby-c13{padding:0;margin:0}.HZWKYxoXby-c21{font-weight:700}.HZWKYxoXby-c7{height:0pt}.HZWKYxoXby-c20{margin-left:36pt}.HZWKYxoXby-c11{height:11pt}.HZWKYxoXby-c16{margin-left:72pt}.HZWKYxoXby-c10{font-style:italic}.title{padding-top:0pt;color:#000000;font-size:26pt;padding-bottom:3pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}.subtitle{padding-top:0pt;color:#666666;font-size:15pt;padding-bottom:16pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}li{color:#000000;font-size:11pt;font-family:"Arial"}p{margin:0;color:#000000;font-size:11pt;font-family:"Arial"}h1{padding-top:20pt;color:#000000;font-size:20pt;padding-bottom:6pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h2{padding-top:18pt;color:#000000;font-size:16pt;padding-bottom:6pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h3{padding-top:16pt;color:#434343;font-size:14pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h4{padding-top:14pt;color:#666666;font-size:12pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h5{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h6{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;font-style:italic;orphans:2;widows:2;text-align:left}</style></head><body class="c14 doc-content"> <p class="HZWKYxoXby-c6"><span class="HZWKYxoXby-c5">Posted by Maddie Stone, Google Project Zero</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span class="HZWKYxoXby-c10">This blog post is an overview of a talk, &ldquo; 0-day In-the-Wild Exploitation in 2022&hellip;so far&rdquo;, </span><span class="HZWKYxoXby-c10">that I gave</span><span class="HZWKYxoXby-c10">&nbsp;at the FIRST conference in June 2022. The slides are available </span><span class="HZWKYxoXby-c1 HZWKYxoXby-c10"><a class="HZWKYxoXby-c81" href="https://github.com/maddiestone/ConPresentations/blob/master/FIRST2022.2022_0days_so_far.pdf">here</a></span><span class="HZWKYxoXby-c12 HZWKYxoXby-c10">.</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c12 HZWKYxoXby-c10"></span></p> <p class="HZWKYxoXby-c6"><span>For the last three years, we&rsquo;ve published annual year-in-review reports of 0-days found exploited in the wild. The most recent of these reports is the </span><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.blogspot.com/2022/04/the-more-you-know-more-you-know-you.html">2021 Year in Review report</a></span><span class="HZWKYxoXby-c5">, which we published just a few months ago in April. While we plan to stick with that annual cadence, we&rsquo;re publishing a little bonus report today looking at the in-the-wild 0-days detected and disclosed in the first half of 2022.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span>As of June 15, 2022, there have been 18 0-days detected and disclosed </span><span>as exploited in-the-wild in 2022</span><span class="HZWKYxoXby-c5">. When we analyzed those 0-days, we found that at least nine of the 0-days are variants of previously patched vulnerabilities. At least half of the 0-days we&rsquo;ve seen in the first six months of 2022 could have been prevented with more comprehensive patching and regression tests. On top of that, four of the 2022 0-days are variants of 2021 in-the-wild 0-days. Just 12 months from the original in-the-wild 0-day being patched, attackers came back with a variant of the original bug. &nbsp;</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p><a id="t.4fab798cceb7e37dcf71e15c259bff9761363678"></a><a id="t.0"></a><table class="HZWKYxoXby-c17"><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c15">Product</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c15">2022 ITW 0-day</span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c15">Variant</span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Windows win32k</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2022/CVE-2022-21882.html">CVE-2022-21882</a></span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1732.html">CVE-2021-1732</a></span><span class="HZWKYxoXby-c5">&nbsp;(2021 itw)</span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">iOS IOMobileFrameBuffer</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://support.apple.com/en-us/HT213053">CVE-2022-22587</a></span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html">CVE-2021-30983</a></span><span class="HZWKYxoXby-c5">&nbsp;(2021 itw)</span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Windows</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-30190">CVE-2022-30190</a></span><span class="HZWKYxoXby-c5">&nbsp;(&ldquo;Follina&rdquo;)</span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444">CVE-2021-40444</a></span><span class="HZWKYxoXby-c5">&nbsp;(2021 itw)</span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Chromium property access interceptors</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://chromereleases.googleblog.com/2022/03/stable-channel-update-for-desktop_25.html">CVE-2022-1096</a></span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://bugs.chromium.org/p/chromium/issues/detail?id=619166">CVE-2016-5128</a></span><span>&nbsp;</span><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30551.html">CVE-2021-30551</a></span><span>&nbsp;(2021 itw) </span><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://bugs.chromium.org/p/project-zero/issues/detail?id=2280">CVE-2022-1232</a></span><span class="HZWKYxoXby-c5">&nbsp;(Addresses incomplete CVE-2022-1096 fix)</span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Chromium v8</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://chromereleases.googleblog.com/2022/04/stable-channel-update-for-desktop_14.html">CVE-2022-1364</a></span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://chromereleases.googleblog.com/2021/03/stable-channel-update-for-desktop_30.html">CVE-2021-21195</a></span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">WebKit</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2022/CVE-2022-22620.html">CVE-2022-22620</a></span><span class="HZWKYxoXby-c5">&nbsp;(&ldquo;Zombie&rdquo;)</span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.blogspot.com/2022/06/an-autopsy-on-zombie-in-wild-0-day.html">Bug was originally fixed in 2013, patch was regressed in 2016</a></span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Google Pixel</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://source.android.com/security/bulletin/pixel/2022-03-01">CVE-2021-39793</a></span><span class="HZWKYxoXby-c5">*</span></p> <p class="HZWKYxoXby-c0 HZWKYxoXby-c11"><span class="HZWKYxoXby-c19"></span></p> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c19">* While this CVE says 2021, the bug was patched and disclosed in 2022</span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cd5297b0855f17c8b4e3ef1d20c6a3656209c7b3">Linux same bug in a different subsystem</a></span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Atlassian Confluence</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://confluence.atlassian.com/doc/confluence-security-advisory-2022-06-02-1130377146.html">CVE-2022-26134</a></span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html">CVE-2021-26084</a></span></p></td></tr><tr class="HZWKYxoXby-c7"><td class="HZWKYxoXby-c9" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c5">Windows</span></p></td><td class="HZWKYxoXby-c2" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-26925">CVE-2022-26925</a></span><span class="HZWKYxoXby-c5">&nbsp;(&ldquo;PetitPotam&rdquo;)</span></p></td><td class="HZWKYxoXby-c3" colspan="1" rowspan="1"> <p class="HZWKYxoXby-c0"><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-36942">CVE-2021-36942</a></span><span class="HZWKYxoXby-c5">&nbsp;(Patch regressed)</span></p></td></tr></table> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span class="HZWKYxoXby-c21">So, what does this mean?</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span>When people think of 0-day exploits, they often think that these exploits are so technologically advanced that there&rsquo;s no hope to catch and prevent them. The data paints a different picture. At least half of the 0-days we&rsquo;ve seen so far this year are closely related to bugs we&rsquo;ve seen before. Our conclusion and findings in the </span><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.blogspot.com/2021/02/deja-vu-lnerability.html">2020 year-in-review report</a></span><span class="HZWKYxoXby-c5">&nbsp;were very similar.</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span>Many of the 2022 in-the-wild 0-days are due to the previous vulnerability not being fully patched. In the case of the Windows win32k and the Chromium property access interceptor bugs, the execution flow that the proof-of-concept exploits took were patched, but the root cause issue was not addressed: attackers were able to come back and trigger the original vulnerability through a different path. And in the case of the WebKit and Windows PetitPotam issues, the original vulnerability had previously been patched, but at some point regressed so that attackers could exploit the same vulnerability again. In the iOS IOMobileFrameBuffer bug, a buffer overflow was addressed by checking that a size was less than a certain number, but it didn&rsquo;t check a minimum bound on that size. For more detailed explanations of three of the 0-days and how they relate to their variants, please see the </span><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://github.com/maddiestone/ConPresentations/blob/master/FIRST2022.2022_0days_so_far.pdf">slides from the talk</a></span><span class="HZWKYxoXby-c5">.</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span class="HZWKYxoXby-c5">When 0-day exploits are detected in-the-wild, it&rsquo;s the failure case for an attacker. It&rsquo;s a gift for us security defenders to learn as much as we can and take actions to ensure that that vector can&rsquo;t be used again. The goal is to force attackers to start from scratch each time we detect one of their exploits: they&rsquo;re forced to discover a whole new vulnerability, they have to invest the time in learning and analyzing a new attack surface, they must develop a brand new exploitation method. To do that effectively, we need correct and comprehensive fixes.</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span class="HZWKYxoXby-c5">This is not to minimize the challenges faced by security teams responsible for responding to vulnerability reports. As we said in our 2020 year in review report: </span></p> <p class="HZWKYxoXby-c6 HZWKYxoXby-c20"><span class="HZWKYxoXby-c12 HZWKYxoXby-c10">Being able to correctly and comprehensively patch isn&#39;t just flicking a switch: it requires investment, prioritization, and planning. It also requires developing a patching process that balances both protecting users quickly and ensuring it is comprehensive, which can at times be in tension. While we expect that none of this will come as a surprise to security teams in an organization, this analysis is a good reminder that there is still more work to be done. </span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c12 HZWKYxoXby-c10"></span></p> <p class="HZWKYxoXby-c6 HZWKYxoXby-c20"><span class="HZWKYxoXby-c10 HZWKYxoXby-c12">Exactly what investments are likely required depends on each unique situation, but we see some common themes around staffing/resourcing, incentive structures, process maturity, automation/testing, release cadence, and partnerships.</span></p> <p class="HZWKYxoXby-c6"><span class="HZWKYxoXby-c5">&nbsp;</span></p> <p class="HZWKYxoXby-c6"><span>Practically, </span><span>some of the</span><span class="HZWKYxoXby-c5">&nbsp;following efforts can help ensure bugs are correctly and comprehensively fixed. Project Zero plans to continue to help with the following efforts, but we hope and encourage platform security teams and other independent security researchers to invest in these types of analyses as well:</span></p><ul style="padding: 0;" class="c13 lst-kix_68660h7uawx-0 start"><li style="margin-left: 46pt;" class="c6 c18 li-bullet-0"><span class="HZWKYxoXby-c5">Root cause analysis</span></li></ul> <p class="HZWKYxoXby-c6 HZWKYxoXby-c16"><span class="HZWKYxoXby-c5">Understanding the underlying vulnerability that is being exploited. Also tries to understand how that vulnerability may have been introduced. Performing a root cause analysis can help ensure that a fix is addressing the underlying vulnerability and not just breaking the proof-of-concept. Root cause analysis is generally a pre-requisite for successful variant and patch analysis.</span></p><ul style="padding: 0;" class="c13 lst-kix_68660h7uawx-0"><li style="margin-left: 46pt;" class="c6 c18 li-bullet-0"><span class="HZWKYxoXby-c5">Variant analysis</span></li></ul> <p class="HZWKYxoXby-c6 HZWKYxoXby-c16"><span class="HZWKYxoXby-c5">Looking for other vulnerabilities similar to the reported vulnerability. This can involve looking for the same bug pattern elsewhere, more thoroughly auditing the component that contained the vulnerability, modifying fuzzers to understand why they didn&rsquo;t find the vulnerability previously, etc. Most researchers find more than one vulnerability at the same time. By finding and fixing the related variants, attackers are not able to simply &ldquo;plug and play&rdquo; with a new vulnerability once the original is patched.</span></p><ul style="padding: 0;" class="c13 lst-kix_68660h7uawx-0"><li style="margin-left: 46pt;" class="c6 c18 li-bullet-0"><span class="HZWKYxoXby-c5">Patch analysis</span></li></ul> <p class="HZWKYxoXby-c6 HZWKYxoXby-c16"><span class="HZWKYxoXby-c5">Analyzing the proposed (or released) patch for completeness compared to the root cause vulnerability. I encourage vendors to share how they plan to address the vulnerability with the vulnerability reporter early so the reporter can analyze whether the patch comprehensively addresses the root cause of the vulnerability, alongside the vendor&rsquo;s own internal analysis.</span></p><ul style="padding: 0;" class="c13 lst-kix_68660h7uawx-0"><li style="margin-left: 46pt;" class="c6 c18 li-bullet-0"><span class="HZWKYxoXby-c5">Exploit technique analysis</span></li></ul> <p class="HZWKYxoXby-c6 HZWKYxoXby-c16"><span>Understanding the primitive gained from the vulnerability and how it&rsquo;s being used. While it&rsquo;s generally industry-standard to patch vulnerabilities, mitigating exploit techniques doesn&rsquo;t happen as frequently. While not every exploit technique will always be able to be mitigated, the hope is that it will become the default rather than the exception. Exploit samples will need to be shared more readily in order for vendors and security researchers to be able to perform exploit technique analysis.</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c6"><span>Transparently sharing these analyses helps the industry as a whole as well. We publish our analyses at </span><span class="HZWKYxoXby-c1"><a class="HZWKYxoXby-c81" href="https://googleprojectzero.github.io/0days-in-the-wild/rca.html">this repository</a></span><span class="HZWKYxoXby-c5">. We encourage vendors and others to publish theirs as well. This allows developers and security professionals to better understand what the attackers already know about these bugs, which hopefully leads to even better solutions and security overall. &nbsp;</span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <p class="HZWKYxoXby-c4"><span class="HZWKYxoXby-c5"></span></p> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://www.blogger.com/profile/08975904405228580347' itemprop='url'/> <a class='g-profile' href='https://www.blogger.com/profile/08975904405228580347' rel='author' title='author profile'> <span itemprop='name'>Google Project Zero</span> </a> </span> </span> <span class='post-timestamp'> at <meta content='https://googleprojectzero.blogspot.com/2022/06/2022-0-day-in-wild-exploitationso-far.html' itemprop='url'/> <a class='timestamp-link' href='https://googleprojectzero.blogspot.com/2022/06/2022-0-day-in-wild-exploitationso-far.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2022-06-30T06:00:00-07:00'>6:00&#8239;AM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://googleprojectzero.blogspot.com/2022/06/2022-0-day-in-wild-exploitationso-far.html#comment-form' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1053444070'> <a href='https://www.blogger.com/post-edit.g?blogID=4838136820032157985&postID=256978548158816980&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=256978548158816980&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=256978548158816980&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=256978548158816980&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=256978548158816980&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=256978548158816980&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> </div></div> <div class="date-outer"> <h2 class='date-header'><span>Thursday, June 23, 2022</span></h2> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioBjlvs-GjJW9ZocxERk7cU6J-bBcWIjauCAzuI6QoMvdQENbSjF6elAZ0yUpLbHfTmOzfdKWBhB_FFR8X9UF1yMqN9XSMmJSUDZ_uVX_zctpmYMaD0G6V7bi68tdJ2C-e3eyM715_cTywzOWAgSbPyazbNtMv65p0lWewhacxCox_vrztKXdRZdjB/s1200/Screenshot%202022-06-22%20at%2016.52.33.png' itemprop='image_url'/> <meta content='4838136820032157985' itemprop='blogId'/> <meta content='5973748726134682294' itemprop='postId'/> <a name='5973748726134682294'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html'>The curious tale of a fake Carrier.app</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5973748726134682294' itemprop='description articleBody'> <style type="text/css">@import url('https://themes.googleusercontent.com/fonts/css?kit=cGvuclDC_Z1vE_cnVEU6Ae_NZQ7StBcqH_vXVqoPMX0');ol{margin:0;padding:0}table td,table th{padding:0}.HovzfPYjjR-c13{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#e0e0e0;border-top-width:1pt;border-right-width:1pt;border-left-color:#e0e0e0;vertical-align:top;border-right-color:#e0e0e0;border-left-width:1pt;border-top-style:solid;background-color:#fafafa;border-left-style:solid;border-bottom-width:1pt;width:468pt;border-top-color:#e0e0e0;border-bottom-style:solid}.HovzfPYjjR-c34{padding-top:0pt;padding-bottom:3pt;line-height:1.5;page-break-after:avoid;text-align:left}.HovzfPYjjR-c15{padding-top:18pt;padding-bottom:6pt;line-height:1.5;page-break-after:avoid;text-align:left}.HovzfPYjjR-c17{text-decoration-skip-ink:none;-webkit-text-decoration-skip:none;color:#1155cc;text-decoration:underline}.HovzfPYjjR-c31{padding-top:0pt;padding-bottom:0pt;line-height:1.5;text-align:center}.HovzfPYjjR-c6{color:#000000;font-weight:400;font-size:11pt;font-family:"Courier New"}.HovzfPYjjR-c9{font-size:10pt;font-family:Consolas,"Courier New";color:#9c27b0;font-weight:400}.HovzfPYjjR-c0{font-size:10pt;font-family:Consolas,"Courier New";color:#000000;font-weight:400}.HovzfPYjjR-c30{font-size:10pt;font-family:Consolas,"Courier New";color:#455a64;font-weight:400}.HovzfPYjjR-c20{border-spacing:0;border-collapse:collapse;margin-right:auto}.HovzfPYjjR-c3{padding-top:0pt;padding-bottom:0pt;line-height:1.5;text-align:left}.HovzfPYjjR-c14{font-size:10pt;font-family:Consolas,"Courier New";color:#3367d6;font-weight:400}.HovzfPYjjR-c16{color:#000000;font-weight:400;font-size:16pt;font-family:"Arial"}.HovzfPYjjR-c5{color:#000000;font-weight:400;font-size:11pt;font-family:"Arial"}.HovzfPYjjR-c27{color:#000000;font-weight:700;font-size:11pt;font-family:"Arial"}.HovzfPYjjR-c23{font-size:10pt;font-family:Consolas,"Courier New";color:#c53929;font-weight:700}.HovzfPYjjR-c22{font-size:10pt;font-family:Consolas,"Courier New";color:#0f9d58;font-weight:400}.HovzfPYjjR-c1{font-size:10pt;font-family:Consolas,"Courier New";color:#616161;font-weight:400}.HovzfPYjjR-c4{font-size:10pt;font-family:Consolas,"Courier New";color:#c53929;font-weight:400}.HovzfPYjjR-c24{padding-top:0pt;padding-bottom:0pt;line-height:1.5;text-align:right}.HovzfPYjjR-c21{color:#000000;font-weight:400;font-size:26pt;font-family:"Arial"}.HovzfPYjjR-c2{text-decoration:none;vertical-align:baseline;font-style:normal}.HovzfPYjjR-c33{background-color:#ffffff;max-width:468pt;padding:72pt 72pt 72pt 72pt}.HovzfPYjjR-c32{margin-left:22.5pt;text-indent:36pt}.HovzfPYjjR-c19{color:inherit;text-decoration:inherit}.HovzfPYjjR-c26{font-weight:700;font-family:"Courier New"}.HovzfPYjjR-c7{font-weight:400;font-family:"Courier New"}.HovzfPYjjR-c28{text-decoration:none;vertical-align:baseline}.HovzfPYjjR-c8{orphans:2;widows:2}.HovzfPYjjR-c29{font-weight:700}.HovzfPYjjR-c18{height:0pt}.HovzfPYjjR-c25{font-style:italic}.HovzfPYjjR-c11{background-color:#00ff00}.HovzfPYjjR-c12{margin-right:-45pt}.HovzfPYjjR-c10{height:11pt}.title{padding-top:0pt;color:#000000;font-size:26pt;padding-bottom:3pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}.subtitle{padding-top:0pt;color:#666666;font-size:15pt;padding-bottom:16pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}li{color:#000000;font-size:11pt;font-family:"Arial"}p{margin:0;color:#000000;font-size:11pt;font-family:"Arial"}h1{padding-top:20pt;color:#000000;font-size:20pt;padding-bottom:6pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h2{padding-top:18pt;color:#000000;font-size:16pt;padding-bottom:6pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h3{padding-top:16pt;color:#434343;font-size:14pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h4{padding-top:14pt;color:#666666;font-size:12pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h5{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;orphans:2;widows:2;text-align:left}h6{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.5;page-break-after:avoid;font-style:italic;orphans:2;widows:2;text-align:left}</style><body class="HovzfPYjjR-c33"> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Posted by Ian Beer, Google Project Zero</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c29">NOTE: This issue was CVE-2021-30983 was fixed in iOS 15.2 in December 2021.</span><span class="HovzfPYjjR-c2 HovzfPYjjR-c27">&nbsp;</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Towards the end of 2021 Google's Threat Analysis Group (TAG) shared an iPhone app</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;with me:</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioBjlvs-GjJW9ZocxERk7cU6J-bBcWIjauCAzuI6QoMvdQENbSjF6elAZ0yUpLbHfTmOzfdKWBhB_FFR8X9UF1yMqN9XSMmJSUDZ_uVX_zctpmYMaD0G6V7bi68tdJ2C-e3eyM715_cTywzOWAgSbPyazbNtMv65p0lWewhacxCox_vrztKXdRZdjB/s1874/Screenshot%202022-06-22%20at%2016.52.33.png" style="display: block; padding: 1em 0; text-align: center;"><img alt="App splash screen showing the Vodafone carrier logo and the text My Vodafone." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioBjlvs-GjJW9ZocxERk7cU6J-bBcWIjauCAzuI6QoMvdQENbSjF6elAZ0yUpLbHfTmOzfdKWBhB_FFR8X9UF1yMqN9XSMmJSUDZ_uVX_zctpmYMaD0G6V7bi68tdJ2C-e3eyM715_cTywzOWAgSbPyazbNtMv65p0lWewhacxCox_vrztKXdRZdjB/s1200/Screenshot%202022-06-22%20at%2016.52.33.png" style="max-height: 750px; max-width: 600px;" title="App splash screen showing the Vodafone carrier logo and the text My Vodafone." /></a></span><img /></p> <p class="HovzfPYjjR-c24 HovzfPYjjR-c8"><span class="HovzfPYjjR-c25">App splash screen showing the Vodafone carrier logo and the text "</span><span class="HovzfPYjjR-c25">My Vodafone</span><span class="c5 c28 c25">" (not the legitimate Vodadone app)</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Although this looks like the real </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://apps.apple.com/gb/app/my-vodafone/id370901726">My Vodafone carrier app</a></span><span>&nbsp;available in the App Store, it didn't come from the App Store and is not the real application from Vodafone. TAG suspects that a target receives a link to this app in an SMS, after the attacker asks the carrier to disable the target's mobile data connection. The SMS claims that in order to restore mobile data connectivity, the target must install the carrier app and includes a link to download and install this fake app.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>This sideloading works because the app is signed with an enterprise certificate, which can be purchased for $299 via the Apple </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://developer.apple.com/programs/enterprise/">Enterprise developer program</a></span><span>. This program allows an eligible enterprise to obtain an Apple-signed </span><span class="HovzfPYjjR-c7">embedded.mobileprovision</span><span>&nbsp;file with the </span><span class="HovzfPYjjR-c7">ProvisionsAllDevices</span><span>&nbsp;key set. An app signed with the developer certificate embedded within that </span><span class="HovzfPYjjR-c7">mobileprovision</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;file can be sideloaded on any iPhone, bypassing Apple's App Store review process. While we understand that the Enterprise developer program is designed for companies to push "trusted apps" to their staff's iOS devices, in this case, it appears that it was being used to sideload this fake carrier app.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>In collaboration with Project Zero, </span><span><a href="https://blog.google/threat-analysis-group/italian-spyware-vendor-targets-users-in-italy-and-kazakhstan/" target="_blank">TAG has published an additional post with more details around the targeting and the actor</a></span><span>. The rest of this blogpost is dedicated to the technical analysis of the app and the exploits contained therein.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.rengd0ayidhp"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">App structure</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The app is broken up into multiple frameworks. </span><span class="HovzfPYjjR-c7">InjectionKit.framework</span><span>&nbsp;is a generic privilege escalation exploit wrapper, exposing the primitives you'd expect (kernel memory access, entitlement injection, </span><span>amfid</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;bypasses) as well as higher-level operations like app installation, file creation and so on.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">Agent.framework</span><span class="HovzfPYjjR-c2 HovzfPYjjR-c5">&nbsp;is partially obfuscated but, as the name suggests, seems to be a basic agent able to find and exfiltrate interesting files from the device like the Whatsapp messages database.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Six privilege escalation exploits are bundled with this app. Five are well-known, publicly available N-day exploits for older iOS versions. The sixth is not like those others at all.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">This blog post is the story of the last exploit and the month-long journey to understand it.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.nr1ejtuvx4nm"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Something's missing? Or am I missing something?</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Although all the exploits were different, five of them shared a common high-level structure. An initial phase where the kernel heap was manipulated to control object placement. Then the triggering of a kernel vulnerability followed by well-known steps to turn that into something useful, perhaps by disclosing kernel memory then building an arbitrary kernel memory write primitive.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The sixth exploit didn't have anything like that.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Perhaps it could be triggering a kernel logic bug like Linuz Henze's </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://github.com/LinusHenze/Fugu14">Fugu14</a></span><span>&nbsp;exploit, or a very bad memory safety issue which gave fairly direct kernel memory access. But neither of those seemed very plausible either. </span><span>It looked, quite simply, like an iOS kernel exploit from a decade ago, except one which was first quite carefully checking that it was only running on an iPhone 12 or 13.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">It contained log messages like:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; printf("Failed to prepare fake vtable: 0x%08x", ret);</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>which seemed to happen far earlier than the exploit could possibly have defeated mitigations like K</span><span>ASLR</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;and PAC.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Shortly after that was this log message:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; printf("Waiting for R/W primitives...");</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Why would you need to wait?</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Then shortly after that:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; printf("Memory read/write and callfunc primitives ready!");</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Up to that point the exploit made only four </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;calls and there were no other obvious attempts at heap manipulation. But there was another log message which started to shed some light:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">&nbsp; printf("Unexpected data read from DCP: 0x%08x", v49);</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.dlybqvef2fq5"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">DCP?</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">In October 2021 Adam Donenfeld tweeted this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><img /></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgizH1ivW5VjBBB2oIDHbvRvevtn3SaYgaWlwf_F_bWSAb9b9kMrycHwATVj_tyHb22sjTc9jJmwQTc-ehvzmruznZtyWToUNiEfyif6nl3latUr3STT8P0YSL0MgxB8_t-CjNLdHITK0kpCcuYPJhFN7zuOX6s1DqOQVQxthrazNfK0ktsvn4Na1hl/s1988/Screenshot%202022-06-22%20at%2016.52.56.png" style="display: block; padding: 1em 0; text-align: center;"><img alt="Screenshot of Tweet from @doadam on 11 Oct 2021, which is a retweet from @AmarSaar on 11 October 2021. The tweet from @AmarSaar reads &#39;So, another IOMFB vulnerability was exploited ITW (15.0.2). I bindiffed the patch and built a POC. And, because it&#39;s a great bug, I just finished writing a short blogpost with the tech details, to share this knowledge :) Check it out! https://saaramar.github.io/IOMFB_integer_overflow_poc/&#39; and the retweet from @doadam reads &#39;This has been moved to the display coprocessor (DCP) starting from 15, at least on iPhone 12 (and most probably other ones as well)&#39;." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgizH1ivW5VjBBB2oIDHbvRvevtn3SaYgaWlwf_F_bWSAb9b9kMrycHwATVj_tyHb22sjTc9jJmwQTc-ehvzmruznZtyWToUNiEfyif6nl3latUr3STT8P0YSL0MgxB8_t-CjNLdHITK0kpCcuYPJhFN7zuOX6s1DqOQVQxthrazNfK0ktsvn4Na1hl/s1200/Screenshot%202022-06-22%20at%2016.52.56.png" style="max-height: 750; max-width: 600px;" title="Screenshot of Tweet from @doadam on 11 Oct 2021, which is a retweet from @AmarSaar on 11 October 2021. The tweet from @AmarSaar reads &#39;So, another IOMFB vulnerability was exploited ITW (15.0.2). I bindiffed the patch and built a POC. And, because it&#39;s a great bug, I just finished writing a short blogpost with the tech details, to share this knowledge :) Check it out! https://saaramar.github.io/IOMFB_integer_overflow_poc/&#39; and the retweet from @doadam reads &#39;This has been moved to the display coprocessor (DCP) starting from 15, at least on iPhone 12 (and most probably other ones as well)&#39;." /></a></span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">DCP is the "Display Co-Processor" which ships with iPhone 12 and above and all M1 Macs.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>There's little public information about the DCP; the most comprehensive comes from the </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://asahilinux.org/">Asahi linux project</a></span><span>&nbsp;which is porting linux to M1 Macs. In their </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://asahilinux.org/2021/08/progress-report-august-2021/">August 2021</a></span><span>&nbsp;and </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://asahilinux.org/2021/10/progress-report-september-2021/">September 2021</a></span><span>&nbsp;updates they discussed their DCP reverse-engineering efforts and the open-source DCP client written by </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://twitter.com/alyssarzg">@alyssarzg</a></span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">. Asahi describe the DCP like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="c3 c8 c32"><span class="c5 c28 c25">On most mobile SoCs, the display controller is just a piece of hardware with simple registers. While this is true on the M1 as well, Apple decided to give it a twist. They added a coprocessor to the display engine (called DCP), which runs its own firmware (initialized by the system bootloader), and moved most of the display driver into the coprocessor. But instead of doing it at a natural driver boundary&#8230; they took half of their macOS C++ driver, moved it into the DCP, and created a remote procedure call interface so that each half can call methods on C++ objects on the other CPU! </span></p> <p class="HovzfPYjjR-c8 HovzfPYjjR-c24"><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://asahilinux.org/2021/08/progress-report-august-2021/">https://asahilinux.org/2021/08/progress-report-august-2021/</a></span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The Asahi linux project reverse-engineered the API to talk to the DCP but they are restricted to using Apple's DCP firmware (loaded by iBoot) - they can't use a custom DCP firmware. Consequently their documentation is limited to the DCP RPC API with few details of the DCP internals.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.nj6hztnr911v"><span class="HovzfPYjjR-c2 HovzfPYjjR-c16">Setting the stage</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Before diving into DCP internals it's worth stepping back a little. What even is a co-processor in a modern, highly integrated SoC (System-on-a-Chip) and what might the consequences of compromising it be?</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Years ago a co-processor would likely have been a physically separate chip. Nowadays a large number of these co-processors are integrated along with their interconnects directly onto a single die, even if they remain fairly independent systems. We can see in this M1 die shot from </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://www.techinsights.com/blog/two-new-apple-socs-two-market-events-apple-a14-and-m1">Tech Insights</a></span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;that the CPU cores in the middle and right hand side take up only around 10% of the die:</span></p> <p class="HovzfPYjjR-c31 HovzfPYjjR-c8"></p> <p class="HovzfPYjjR-c8 HovzfPYjjR-c31"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjtJjSN0qdOa1cKBG72s9uuwcVKU5evSg9CiIPtpbbFox0fGgW7XZQU1Jj4IezjIdHC23sJbnklT6acyTFiqB-0-qmcj35Gq-ZZyTHP0DcfFkBztA0DL2P3lhYy2n0k8wgzmzaYX8IMeKosr4uuWMXT-wplsuJQmfR4LDgFzWAUZARvx5rfWjWiusz/s1116/Screenshot%202022-06-22%20at%2016.53.12.png" style="display: block; padding: 1em 0; text-align: center;"><img alt="M1 die-shot from techinsights.com with possible location of DCP highlighted." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjtJjSN0qdOa1cKBG72s9uuwcVKU5evSg9CiIPtpbbFox0fGgW7XZQU1Jj4IezjIdHC23sJbnklT6acyTFiqB-0-qmcj35Gq-ZZyTHP0DcfFkBztA0DL2P3lhYy2n0k8wgzmzaYX8IMeKosr4uuWMXT-wplsuJQmfR4LDgFzWAUZARvx5rfWjWiusz/s1116/Screenshot%202022-06-22%20at%2016.53.12.png" style="max-height: 750; max-width: 600px;" title="M1 die-shot from techinsights.com with possible location of DCP highlighted." /></a></span></p> <p class="HovzfPYjjR-c24 HovzfPYjjR-c8"><span class="c5 c25 c28">M1 die-shot from techinsights.com with possible location of DCP added</span></p> <p class="HovzfPYjjR-c24 HovzfPYjjR-c8"><span class="HovzfPYjjR-c17 HovzfPYjjR-c25"><a class="HovzfPYjjR-c191" href="https://www.techinsights.com/blog/two-new-apple-socs-two-market-events-apple-a14-and-m1">https://www.techinsights.com/blog/two-new-apple-socs-two-market-events-apple-a14-and-m1</a></span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Companies like </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://www.systemplus.fr/">SystemPlus</a></span><span>&nbsp;perform </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://www.systemplus.fr/wp-content/uploads/2020/12/SP20608-Apple-M1-System-on-Chip-Sample.pdf">very thorough analysis of these dies</a></span><span>. Based on their analysis the DCP is likely the rectangular region indicated on this M1 die. It takes up around the same amount of space as the four high-</span><span>efficiency</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;cores seen in the centre, though it seems to be mostly SRAM.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>With just this low-resolution image it's not really possible to say much more about the functionality or capabilities of the DCP and what level of system access it has. To answer those questions we'll need to take a look at the firmware.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.mnw2kq5jkaze"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">My kingdom for a .dSYM!</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The first step is to get the DCP firmware image. iPhones (and now M1 macs) use </span><span class="HovzfPYjjR-c7">.ipsw</span><span>&nbsp;files for system images. An </span><span class="HovzfPYjjR-c7">.ipsw</span><span>&nbsp;is really just a </span><span class="HovzfPYjjR-c7">.zip</span><span>&nbsp;archive and the </span><span class="HovzfPYjjR-c7">Firmware/</span><span>&nbsp;folder in the extracted </span><span class="HovzfPYjjR-c7">.zip</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;contains all the firmware for the co-processors, modems etc. The DCP firmware is this file:</span></p><hr style="display: none; page-break-before: always;" /> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; Firmware/dcp/iphone13dcp.im4p</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The </span><span class="HovzfPYjjR-c7">im4p</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;in this case is just a 25 byte header which we can discard:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; $ dd if=iphone13dcp.im4p of=iphone13dcp bs=25 skip=1</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c2 HovzfPYjjR-c6">&nbsp; $ file iphone13dcp</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; iphone13dcp: Mach-O 64-bit preload executable arm64</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>It's a Mach-O! Running </span><span class="HovzfPYjjR-c7">nm -a</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;to list all symbols shows that the binary has been fully stripped:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; $ nm -a iphone13dcp</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&nbsp; iphone13dcp: no symbols</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Function names make understanding code significantly easier. From looking at the handful of strings in the exploit some of them looked like they might be referencing symbols in a DCP firmware image ("</span><span class="HovzfPYjjR-c7">M3_CA_ResponseLUT read: 0x%08x</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">" for example) so I thought perhaps there might be a DCP firmware image where the symbols hadn't been stripped.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Since the firmware images are distributed as </span><span class="HovzfPYjjR-c7">.zip</span><span>&nbsp;files and Apple's servers support range requests with a bit of python and the </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://github.com/marcograss/partialzip">partialzip</a></span><span>&nbsp;tool</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;we can relatively easily and quickly get every beta and release DCP firmware. I checked over 300 distinct images; every single one was stripped.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Guess we'll have to do this the hard way!</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.m9onjpj2j9i"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Day 1; Instruction 1</span></h2> <p class="c3 c8 c12"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">$ otool -h raw_fw/iphone13dcp</span></p> <p class="c3 c8 c12 c10"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2"></span></p> <p class="c3 c8 c12"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">raw_fw/iphone13dcp:</span></p> <p class="c3 c8 c12"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">Mach header</span></p> <p class="c3 c8 c12"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">magic &nbsp; &nbsp; &nbsp;cputype &nbsp; cpusubtype caps filetype ncmds sizeofcmds flags</span></p> <p class="c3 c8 c12"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">0xfeedfacf 0x100000C 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0x00 5 &nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; 2240 &nbsp; &nbsp; &nbsp; 0x00000001</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>That </span><span class="HovzfPYjjR-c7">cputype</span><span>&nbsp;is plain </span><span class="HovzfPYjjR-c7">arm64</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;(ArmV8) without pointer authentication support. The binary is fairly large (3.7MB) and IDA's autoanalysis detects over 7000 functions.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">With any brand new binary I usually start with a brief look through the function names and the strings. The binary is stripped so there are no function name symbols but there are plenty of C++ function names as strings:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><img /></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY8rBSaTDR2W5pSgk9ssaCqN8M8Nuhd5_x6FkNSqOI-jRDFVab_jrrkZlN1DS2FKf9zeAPPDFkE30kNCPpN3PES9RdvBLj4L6G78zq134bTQcR1VEe7J30tYPoqqZ82z1cPwUcvF2wzfoOEbDf3l_4ucxpuOZFC2NLyrMYV_luJ_5dysxanajqsi-N/s1830/Screenshot%202022-06-22%20at%2016.53.26.png" style="display: block; padding: 1em 0; text-align: center;"><img alt="A short list of C++ prototypes like IOMFB::UPBlock_ALSS::init(IOMFB::UPPipe *)." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY8rBSaTDR2W5pSgk9ssaCqN8M8Nuhd5_x6FkNSqOI-jRDFVab_jrrkZlN1DS2FKf9zeAPPDFkE30kNCPpN3PES9RdvBLj4L6G78zq134bTQcR1VEe7J30tYPoqqZ82z1cPwUcvF2wzfoOEbDf3l_4ucxpuOZFC2NLyrMYV_luJ_5dysxanajqsi-N/s1200/Screenshot%202022-06-22%20at%2016.53.26.png" style="max-height: 750; max-width: 600px;" title="A short list of C++ prototypes like IOMFB::UPBlock_ALSS::init(IOMFB::UPPipe *)." /></a></span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The cross-references to those strings look like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.c7f36f1411586a1b165d5a48e181a07b7b9d07a6"></a><a id="t.0"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">log</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c4">0x40000001LL</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">"UPBlock_ALSS.cpp"</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c4">341</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">"%s: capture buffer exhausted, aborting capture\n"</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">"void IOMFB::UPBlock_ALSS::send_data(uint64_t, uint32_t)"</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>This is almost certainly a logging macro which expands </span><span class="HovzfPYjjR-c7">__FILE__</span><span>,</span><span class="HovzfPYjjR-c7">&nbsp;__LINE__</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">__PRETTY_FUNCTION__</span><span>. This allows us to start renaming functions and finding vtable pointers.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.72tz1dtagcu2"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Object structure</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">From the Asahi linux blog posts we know that the DCP is using an Apple-proprietary RTOS called RTKit for which there is very little public information. There are some strings in the binary with the exact version:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">ADD &nbsp;X8, X8, #aLocalIphone13d@PAGEOFF ; "local-iphone13dcp.release"</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">ADD &nbsp;X9, X9, #aRtkitIos182640@PAGEOFF ; "RTKit_iOS-1826.40.9.debug"</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The code appears to be predominantly C++. There appear to be multiple C++ object hierarchies; those involved with this vulnerability look a bit like IOKit C++ objects. Their common base class looks like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.23741390b29a0e8a199a26eb39699e3e43f7695e"></a><a id="t.1"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;__cppobj RTKIT_RC_RTTI_BASE</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; RTKIT_RC_RTTI_BASE_vtbl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">__vftable </span><span class="HovzfPYjjR-c30">/*VFT*/</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t refcnt</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t </span><span class="HovzfPYjjR-c9">typeid</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">};</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">(These structure definitions are in the format IDA uses for C++-like objects)</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The </span><span class="HovzfPYjjR-c7">RTKit</span><span>&nbsp;base class has a vtable pointer, a reference count and a four-byte Run Time Type Information (RTTI) field - a 4-byte ASCII identifier like </span><span class="HovzfPYjjR-c7">BLHA</span><span>, </span><span class="HovzfPYjjR-c7">WOLO</span><span>, </span><span class="HovzfPYjjR-c7">MMAP</span><span>, </span><span class="HovzfPYjjR-c7">UNPI</span><span>, </span><span class="HovzfPYjjR-c7">OSST</span><span>, </span><span class="HovzfPYjjR-c7">OSBO</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;and so on. These identifiers look a bit cryptic but they're quite descriptive once you figure them out (and I'll describe the relevant ones as we encounter them.)</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The base type has the following associated vtable:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.e2f588f986d4c4d814dde7976c00d512e7353bbe"></a><a id="t.2"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c30">/*VFT*/</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;RTKIT_RC_RTTI_BASE_vtbl</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">take_ref</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">drop_ref</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">take_global_type_ref</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">drop_global_type_ref</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">getClassName</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">dtor_a</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__cdecl </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">unk</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c0">RTKIT_RC_RTTI_BASE </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">};</span></p></td></tr></table><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.17hwrgmah5ee"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Exploit flow</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The exploit running in the app starts by opening an IOKit user client for the </span><span class="HovzfPYjjR-c7">AppleCLCD2</span><span>&nbsp;service. </span><span class="HovzfPYjjR-c7">AppleCLCD</span><span>&nbsp;seems to be the application processor of </span><span class="HovzfPYjjR-c7">IOMobileFrameBuffer</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">AppleCLCD2</span><span>&nbsp;the </span><span class="HovzfPYjjR-c7">DCP</span><span>&nbsp;version.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The exploit only calls 3 different external method selectors on the </span><span class="HovzfPYjjR-c7">AppleCLCD2</span><span>&nbsp;user client: </span><span class="HovzfPYjjR-c7">68</span><span>, </span><span class="HovzfPYjjR-c7">78</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">79</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The one with the largest and most interesting-looking input is 78, which corresponds to this user client method in the kernel driver:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.c1d0de88bea2ae99b6a4f974f60cac134013db41"></a><a id="t.3"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c14">IOReturn</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c14">IOMobileFramebufferUserClient</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">s_set_block</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c14">IOMobileFramebufferUserClient</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">reference</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c14">IOExternalMethodArguments</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">args</span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">const</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;__int64 </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">extra_args</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u8 </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">structureInput</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c10"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; structureInput </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">structureInput</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">if</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;structureInput </span><span class="HovzfPYjjR-c1">&amp;&amp;</span><span class="HovzfPYjjR-c0">&nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalarInputCount </span><span class="HovzfPYjjR-c1">&gt;=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">2</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">if</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalarInputCount </span><span class="HovzfPYjjR-c1">==</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">2</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; extra_args </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0LL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">else</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; extra_args </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalarInput </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">2</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c10"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">framebuffer_ap</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">set_block_dcp</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">task</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalarInput</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">],</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalarInput</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">1</span><span class="HovzfPYjjR-c1">],</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;extra_args</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalarInputCount </span><span class="HovzfPYjjR-c1">-</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">2</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;structureInput</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">structureInputSize</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">}</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">else</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0xE00002C2</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">}</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>this unpacks the </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;arguments and passes them to:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.4b4f98b94b8ed8638b5222e4f9d81049bbe69fdb"></a><a id="t.4"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c14">IOMobileFramebufferAP</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">set_block_dcp</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c14">IOMobileFramebufferAP</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; task </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">task</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;first_scalar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;second_scalar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">const</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;__int64 </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">pointer_to_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;scalar_input_count_minus_2</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">const</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;__int8 </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">struct_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;__int64 struct_input_size</span><span class="HovzfPYjjR-c1">)</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">This method uses some autogenerated code to serialise the external method arguments into a buffer like this: </span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.26b4f1ef327e79bf7a370b395d86bddb90eb464f"></a><a id="t.5"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">arg_struct</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;task</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;task</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u64 scalar_input_0</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u64 scalar_input_1</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u64</span><span class="HovzfPYjjR-c1">[]</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;remaining_scalar_inputs</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u64 cntExtraScalars</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u8</span><span class="HovzfPYjjR-c1">[]</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;structInput</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u64 </span><span class="HovzfPYjjR-c14">CntStructInput</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>which is then passed to </span><span class="HovzfPYjjR-c7">UnifiedPipeline2::rpc</span><span>&nbsp;along with a 4-byte ASCII method identifier ('</span><span class="HovzfPYjjR-c7">A435</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">' here):</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.afc7096b3986ce85a82073984786eb19b4fcdb59"></a><a id="t.6"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c14">UnifiedPipeline2</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">rpc</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">'A435'</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; arg_struct</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c4">0x105Cu</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">retval_buf</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c4">4u</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">UnifiedPipeline2::rpc</span><span>&nbsp;calls </span><span class="HovzfPYjjR-c7">DCPLink::rpc</span><span>&nbsp;which calls </span><span class="HovzfPYjjR-c7">AppleDCPLinkService::rpc</span><span>&nbsp;to perform one more level of serialisation which packs the method identifier and a "stream identifier" together with the </span><span class="HovzfPYjjR-c7">arg_struct</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;shown above.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">AppleDCPLinkService::rpc</span><span>&nbsp;then calls </span><span class="HovzfPYjjR-c7">rpc_caller_gated</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;to allocate space in a shared memory buffer, copy the buffer into there then signal to the DCP that a message is available.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Effectively the implementation of the </span><span class="HovzfPYjjR-c7">IOMobileFramebuffer</span><span>&nbsp;user client has been moved on to the DCP and the external method interface is now a proxy shim, via shared memory, to the actual implementations of the external methods which </span><span>run on the DCP.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.5nfahlo9nbh6"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Exploit flow: the other side</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The next challenge is to find where the messages start being processed on the DCP. Looking through the log strings there's a function which is clearly called &#8203;&#8203;</span><span class="HovzfPYjjR-c7">rpc_calle</span><span class="HovzfPYjjR-c26">e</span><span class="HovzfPYjjR-c7">_gated</span><span>&nbsp;- quite likely that's the receive side of the function </span><span class="HovzfPYjjR-c7">rpc_calle</span><span class="HovzfPYjjR-c26">r</span><span class="HovzfPYjjR-c7">_gated</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;we saw earlier.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">rpc_callee_gated</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;unpacks the wire format then has an enormous switch statement which maps all the 4-letter RPC codes to function pointers:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.47d68344bf5cd802c2cfc796e38eefd94678d525"></a><a id="t.7"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">switch</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;rpc_id </span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">case</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c22">'A000'</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">goto</span><span class="HovzfPYjjR-c0">&nbsp;LABEL_146</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">case</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c22">'A001'</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler_fptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;callback_handler_A001</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">break</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">case</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c22">'A002'</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler_fptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;callback_handler_A002</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">break</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">case</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c22">'A003'</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler_fptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;callback_handler_A003</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">break</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">case</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c22">'A004'</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler_fptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;callback_handler_A004</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">break</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">case</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c22">'A005'</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler_fptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;callback_handler_A005</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">break</span><span class="HovzfPYjjR-c1">;</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">At the the bottom of this switch statement is the invocation of the callback handler:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.727f8d6109f87f45ecfc47e4cbc67fff73f299cf"></a><a id="t.8"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">ret </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;handler_fptr</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; meta</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; in_struct_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; in_struct_size</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out_struct_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out_struct_size</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">in_struct_ptr</span><span>&nbsp;points to a copy of the serialised </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;arguments we saw being serialized earlier on the application processor:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.a1bc79b6e0e53aa6513e954a3be969c86fa9de29"></a><a id="t.9"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">arg_struct</span><span class="HovzfPYjjR-c1">:</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;task</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;task</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u64 scalar_input_0</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u64 scalar_input_1</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u64</span><span class="HovzfPYjjR-c1">[]</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;remaining_scalar_inputs</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u32 cntExtraScalars</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u8</span><span class="HovzfPYjjR-c1">[]</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;structInput</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; u64 cntStructInput</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The callback unpacks that buffer and calls a C++ virtual function:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.423c597cfa08d39f62002779d1150a8e593d7557"></a><a id="t.10"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">callback_handler_A435</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; u8</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;meta</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">args</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t args_size</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">out_struct_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp; uint32_t out_struct_size</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; int64 instance_id</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t instance</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;err</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;retval</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;result</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c10"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; instance_id </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;meta</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">instance_id</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; instance </span><span class="HovzfPYjjR-c1">=</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; global_instance_table</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c0">instance_id</span><span class="HovzfPYjjR-c1">].</span><span class="HovzfPYjjR-c14">IOMobileFramebufferType</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">if</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">!</span><span class="HovzfPYjjR-c0">instance </span><span class="HovzfPYjjR-c1">)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; log_fatal</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">"IOMFB: %s: no instance for instance ID: %u\n"</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">"static T *IOMFB::InstanceTracker::instance"</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">"(IOMFB::InstanceTracker::tracked_entity_t, uint32_t)"</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c22">" [T = IOMobileFramebuffer]"</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; instance_id</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">}</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; err </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1 HovzfPYjjR-c11">(</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c11">instance</span><span class="HovzfPYjjR-c1 HovzfPYjjR-c11">-</span><span class="HovzfPYjjR-c4 HovzfPYjjR-c11">16</span><span class="HovzfPYjjR-c1 HovzfPYjjR-c11">)-&gt;</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c11">vtable_0x378</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c30">// virtual call</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">instance</span><span class="HovzfPYjjR-c1">-</span><span class="HovzfPYjjR-c4">16</span><span class="HovzfPYjjR-c1">),</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">task</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalar_input_0</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">scalar_input_1</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">cntExtraScalars</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">structInput</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">cntStructInput</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c10"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; retval </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;convert_error</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">err</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; result </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_DWORD </span><span class="HovzfPYjjR-c1">*)</span><span class="HovzfPYjjR-c0">out_struct_ptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;retval</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;result</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The challenge here is to figure out where</span><span>&nbsp;</span><span class="HovzfPYjjR-c11">that virtual call</span><span>&nbsp;goes</span><span>. The object is being looked up in a global table based on the instance id. We can't just set a breakpoint and whilst emulating the firmware is probably possible that would likely be a long project in itself. I took a hackier approach: we know that the vtable needs to be at least </span><span class="HovzfPYjjR-c7">0x380</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;bytes large so just go through all those vtables, decompile them and see if the prototypes look reasonable!</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>There's one clear match in the vtable for the </span><span class="HovzfPYjjR-c7">UNPI</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;type:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2"></span></p><a id="t.ac38f56155b7d2697b0aee9ae6858f6b42815b34"></a><a id="t.11"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">UNPI</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">set_block</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; UNPI</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;task</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;caller_task_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;first_scalar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;second_scalar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; uint32_t cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; uint8_t </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; uint64_t structure_input_size</span><span class="HovzfPYjjR-c1">)</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Here's my reversed implementation of </span><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">UNPI::set_block</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2"></span></p><a id="t.3aba48cdaac58ae867b60889bc2f2ff94e4953a6"></a><a id="t.12"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">UNPI</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">set_block</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; UNPI</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;task</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;caller_task_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;first_scalar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;second_scalar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; uint32_t cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; uint8_t </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; uint64_t structure_input_size</span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;block_handler_holder </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">holder</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;metadispatcher metadisp</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c10"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">if</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;second_scalar_input </span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x80000001LL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; holder </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c14">UPPipeDCP_H13P</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">block_handler_holders</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">if</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">!</span><span class="HovzfPYjjR-c0">holder </span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x8000000BLL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c10"><span class="HovzfPYjjR-c0 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">address_of_some_zerofill_static_buffer </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">unk_3B8D18</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">handlers_holder </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;holder</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">structure_input_buffer </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;structure_input_buffer</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">structure_input_size </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;structure_input_size</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">cnt_remaining_sclar_input </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">some_flags </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x40000000LL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">dispatcher_fptr </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;a_dispatcher</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; metadisp</span><span class="HovzfPYjjR-c1">.</span><span class="HovzfPYjjR-c0">offset_of_something_which_looks_serialization_related </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">off_1C1308</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;metadispatch</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">holder</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;first_scalar_input</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">1</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;caller_task_ptr</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">metadisp</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>This method wraps up the arguments into another structure I've called </span><span class="HovzfPYjjR-c7">metadispatcher</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.70518115c511a294cd855553b9003a0771a08ccd"></a><a id="t.13"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;__attribute__</span><span class="HovzfPYjjR-c1">((</span><span class="HovzfPYjjR-c0">aligned</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c4">8</span><span class="HovzfPYjjR-c1">)))</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;metadispatcher</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t address_of_some_zerofill_static_buffer</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t some_flags</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;__int64 </span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">__fastcall </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">dispatcher_fptr</span><span class="HovzfPYjjR-c1">)(</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;metadispatcher </span><span class="HovzfPYjjR-c1">*,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*,</span><span class="HovzfPYjjR-c0">&nbsp;__int64</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;_QWORD</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t offset_of_something_which_looks_serialization_related</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;block_handler_holder </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">handlers_holder</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t structure_input_buffer</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t structure_input_size</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint32_t cnt_remaining_sclar_input</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">};</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">That metadispatcher object is then passed to this method:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.9e3136a3d4346cb21c1c8dc0948c6e7439c8fc5f"></a><a id="t.14"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;metadispatch</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">holder</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;first_scalar_input</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">1</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;caller_task_ptr</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">metadisp</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">In there we reach this code:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.b1eaf3e2e954d8f37bc987b98c30e92ce161e849"></a><a id="t.15"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; block_type_handler </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;lookup_a_handler_for_block_type_and_subtype</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a1</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;first_scalar_input</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c30">// block_type</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a3</span><span class="HovzfPYjjR-c1">);</span><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c30">// subtype</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The exploit calls this </span><span class="HovzfPYjjR-c7">set_block</span><span>&nbsp;external method twice, passing two different values for </span><span class="HovzfPYjjR-c7">first_scalar_input</span><span>, </span><span class="HovzfPYjjR-c7">7</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">19</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">. Here we can see that those correspond to looking up two different block handler objects here.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The lookup function searches a linked list of block handler structures; the head of the list is stored at offset </span><span class="HovzfPYjjR-c7">0x1448</span><span>&nbsp;in the </span><span class="HovzfPYjjR-c7">UPPipeDCP_H13P</span><span>&nbsp;object and registered dynamically by a method I've named </span><span class="HovzfPYjjR-c7">add_handler_for_block_type</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.0dbaa54d4462638b9beda378f3267a7a7c4ded25"></a><a id="t.16"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">add_handler_for_block_type</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;block_handler_holder </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">handler_list</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">handler</span><span class="HovzfPYjjR-c1">)</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The logging code tells us that this is in a file called </span><span class="HovzfPYjjR-c7">IOMFBBlockManager.cpp</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">. IDA finds 44 cross-references to this method, indicating that there are probably that many different block handlers. The structure of each registered block handler is something like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.3c5d4c46eb785d82b4debfb43373bde140bc52fe"></a><a id="t.17"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;__cppobj </span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">:</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;RTKIT_RC_RTTI_BASE</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t field_16</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;handler_inner_types_entry </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">inner_types_array</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t n_inner_types_array_entries</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t field_36</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint8_t can_run_without_commandgate</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t block_type</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t list_link</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t list_other_link</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t some_other_type_field</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t some_other_type_field2</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t expected_structure_io_size</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint32_t field_76</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t getBlock_Impl</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t setBlock_Impl</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t field_96</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint64_t back_ptr_to_UPPipeDCP_H13P</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">};</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The RTTI type is </span><span class="HovzfPYjjR-c7">BLHA</span><span>&nbsp;(</span><span class="HovzfPYjjR-c7">BL</span><span>ock </span><span class="HovzfPYjjR-c7">HA</span><span>ndler.)</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">For example, here's the codepath which builds and registers block handler type 24:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.15a6e240c53ab46ec843eed2902a63a7ce3a078d"></a><a id="t.18"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24 </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*)</span><span class="HovzfPYjjR-c14">CXXnew</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c4">112LL</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">__vftable </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c14">BlockHandler_vtbl</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*)</span><span class="HovzfPYjjR-c0">BLHA_super_vtable</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">block_type </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">24</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">refcnt </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">1</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">can_run_without_commandgate </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">some_other_type_field </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0LL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">expected_structure_io_size </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0xD20</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">typeid</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;typeid_BLHA</span><span class="HovzfPYjjR-c1">();</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c9">typeid</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">typeid</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">modify_typeid_ref</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">typeid</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">1</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">__vftable </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;vtable_BLHA_subclass_type_24</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">inner_types_array </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0LL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">n_inner_types_array_entries </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">getBlock_Impl </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;BLHA_24_getBlock_Impl</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">setBlock_Impl </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;BLHA_24_setBlock_Impl</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">field_96 </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0LL</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">BLHA_24</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">back_ptr_to_UPPipeDCP_H13P </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;a1</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">add_handler_for_block_type</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">list_holder</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;BLHA_24</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Each block handler optionally has </span><span class="HovzfPYjjR-c7">getBlock_Impl</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;function pointers which appear to implement the actual setting and getting operations.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>We can go through all the callsites which add block handlers; tell IDA the type of the arguments and name all the </span><span class="HovzfPYjjR-c7">getBlock</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">setBlock</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;implementations:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><img /></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-Z34Qgm9fUE2rzMwJWQ3j-w7InvtfHj5fs2qctSh0tTFmMbUpnrsQC4rUrhMf3_83uHAFinlM6xKqKXgUc2QR5IfL0gf4YEBM9Rqgrc6sNYsaCZ-JAe0PHlGa9VYcBgWfTqj5rTtin1mWTDG-I8K5M41EhA64KLNV54Sv9lvtbYIrkY2j37X6SniB/s1436/Screenshot%202022-06-22%20at%2016.53.47.png" style="display: block; padding: 1em 0; text-align: center;"><img alt="The IDA Pro Names window showing a list of symbols like BLHA_15_getBlock_Impl." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-Z34Qgm9fUE2rzMwJWQ3j-w7InvtfHj5fs2qctSh0tTFmMbUpnrsQC4rUrhMf3_83uHAFinlM6xKqKXgUc2QR5IfL0gf4YEBM9Rqgrc6sNYsaCZ-JAe0PHlGa9VYcBgWfTqj5rTtin1mWTDG-I8K5M41EhA64KLNV54Sv9lvtbYIrkY2j37X6SniB/s1200/Screenshot%202022-06-22%20at%2016.53.47.png" style="max-height: 750; max-width: 600px;" title="The IDA Pro Names window showing a list of symbols like BLHA_15_getBlock_Impl." /></a></span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>You can perhaps see where this is going: that's looking like really quite a lot of reachable attack surface! Each of those </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span>&nbsp;functions is reachable by passing a different value for the first scalar argument to </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span>&nbsp;</span><span class="HovzfPYjjR-c7">78</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>There's a little bit more reversing though to figure out how exactly to get controlled bytes to those </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;functions:</span></p><h2 class="HovzfPYjjR-c8 HovzfPYjjR-c15" id="h.7aa6aljwlb56"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Memory Mapping</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The raw "block" input to each of those </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span>&nbsp;methods isn't passed inline in the </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span>&nbsp;structure input. There's another level of indirection: each individual block handler structure has an array of supported "subtypes" which contains metadata detailing where to find the (userspace) pointer to that subtype's input data in the </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;structure input. The first dword in the structure input is the id of this subtype - in this case for the block handler type 19 the metadata array has a single entry:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2">&lt;2, 0, 0x5F8, 0x600&gt;</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The first value (</span><span class="HovzfPYjjR-c7">2</span><span>) is the subtype id and </span><span class="HovzfPYjjR-c7">0x5f8</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">0x600</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;tell the DCP from what offset in the structure input data to read a pointer and size from. The DCP then requests a memory mapping from the AP for that memory from the calling task:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.aba9dc90c6ed53b6789430b30f81bcfaea4d57c4"></a><a id="t.19"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;wrap_MemoryDescriptor</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">withAddressRange</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c1">*)(</span><span class="HovzfPYjjR-c0">structure_input_buffer </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;addr_offset</span><span class="HovzfPYjjR-c1">),</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*)(</span><span class="HovzfPYjjR-c0">structure_input_buffer </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;size_offset</span><span class="HovzfPYjjR-c1">),</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; caller_task_ptr</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>We saw earlier that the AP sends the DCP the </span><span class="HovzfPYjjR-c7">struct task</span><span>&nbsp;pointer of the calling task; when the DCP requests a memory mapping from a user task it sends those raw task struct pointers back to the AP such that the kernel can perform the mapping from the correct task. The memory mapping is abstracted as an </span><span class="HovzfPYjjR-c7">MDES</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;object on the DCP side; the implementation of the mapping involves the DCP making an RPC to the AP:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.3170af9bf4e5590254e3fb8ce48d68439d2d1c04"></a><a id="t.20"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">make_link_call</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c22">'D453'</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">req</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x20</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">&amp;</span><span class="HovzfPYjjR-c0">resp</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x14</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">which corresponds to a call to this method on the AP side:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.6497588dbb4a0e06e642bb1567a0fe45e731eabb"></a><a id="t.21"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">IOMFB</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c14">MemDescRelay</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">withAddressRange</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;task</span><span class="HovzfPYjjR-c1">*,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c1">*,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">long</span><span class="HovzfPYjjR-c1">*)</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The DCP calls </span><span class="HovzfPYjjR-c7">::prepare</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">::map</span><span>&nbsp;on the returned </span><span class="HovzfPYjjR-c7">MDES</span><span>&nbsp;object (exactly like an </span><span class="HovzfPYjjR-c7">IOMemoryDescriptor</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;object in IOKit), gets the mapped pointer and size to pass via a few final levels of indirection to the block handler:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.9bfd168ba40a9f143ab7f16183ab117679ba2dbc"></a><a id="t.22"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">a_descriptor_with_controlled_stuff</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">dispatcher_fptr</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; a_descriptor_with_controlled_stuff</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; block_type_handler</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; important_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; important_size</span><span class="HovzfPYjjR-c1">);</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>where the </span><span class="HovzfPYjjR-c7">dispatcher_fptr</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;looks like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.acd62f1b5ef2e8ae92523e3f984117951fec44d7"></a><a id="t.23"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">a_dispatcher</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;metadispatcher </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">disp</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">block_handler</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; __int64 controlled_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;controlled_size</span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;block_handler</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c14">BlockHandler_setBlock</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;block_handler</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;disp</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;disp</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">structure_input_size</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;disp</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;disp</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">cnt_remaining_sclar_input</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;disp</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">handlers_holder</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">gate</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;controlled_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;controlled_size</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">You can see here just how useful it is to keep making structure definitions while reversing; there are so many levels of indirection that it's pretty much impossible to keep it all in your head.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c7">BlockHandler_setBlock</span><span>&nbsp;is a virtual method on </span><span class="HovzfPYjjR-c7">BLHA</span><span>.</span><span>&nbsp;This is the implementation for </span><span class="HovzfPYjjR-c7">BLHA</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;19:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.54f6196429ae58c591e0fbda962486be871b857c"></a><a id="t.24"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c14">BlockHandler19</span><span class="HovzfPYjjR-c1">::</span><span class="HovzfPYjjR-c0">setBlock</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; int64 structure_input_size</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; int64 </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">CommandGate</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">gate</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;mapped_mdesc_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;mapped_mdesc_length</span><span class="HovzfPYjjR-c1">)</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>This uses a Command Gate (</span><span class="HovzfPYjjR-c7">GATI</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">) object (like a call gate in IOKit to serialise calls) to finally get close to actually calling the setBlock_Impl function.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>We need to reverse the </span><span class="HovzfPYjjR-c7">gate_context</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;structure to follow the controlled data through the gate:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.ecbfc354e58e0a03f109ff9486e9e7688b91b2e0"></a><a id="t.25"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;__attribute__</span><span class="HovzfPYjjR-c1">((</span><span class="HovzfPYjjR-c0">aligned</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c4">8</span><span class="HovzfPYjjR-c1">)))</span><span class="HovzfPYjjR-c0 HovzfPYjjR-c2">&nbsp;gate_context</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">BlockHandler</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">the_target_this</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t structure_input_buffer</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint32_t cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint32_t field_28</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint64_t controlled_ptr</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp;uint32_t controlled_length</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">};</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The callgate object uses that context object to finally call the BLHA setBlock handler:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.af3652c5bd10314e902473b353a7422786c1de2f"></a><a id="t.26"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">callback_used_by_callgate_in_block_19_setBlock</span><span class="HovzfPYjjR-c1">(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">UnifiedPipeline</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">parent_pipeline</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;gate_context </span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">context</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; int64 a3</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; int64 a4</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; int64 a5</span><span class="HovzfPYjjR-c1">)</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">return</span><span class="HovzfPYjjR-c0">&nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">the_target_this</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">setBlock_Impl</span><span class="HovzfPYjjR-c1">)(</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">the_target_this</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">back_ptr_to_UPPipeDCP_H13P</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">controlled_ptr</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">controlled_length</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.3xz0wc9abhwz"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">SetBlock_Impl</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>And finally we've made it through the whole callstack following the controlled data from </span><span class="HovzfPYjjR-c7">IOConnectCallMethod</span><span>&nbsp;in userspace on the AP to the </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span>&nbsp;methods on the DCP!</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The prototype of the </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;methods looks like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.ce1b657ebc4685a8be9f9a3720b828c0f9a2d7ce"></a><a id="t.27"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">setBlock_Impl</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">struct</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">UPPipeDCP_H13P</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">pipe_parent</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">structure_input_buffer</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;cnt_remaining_scalar_inputs</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">void</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;ptr_via_memdesc</span><span class="HovzfPYjjR-c1">,</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="HovzfPYjjR-c9">unsigned</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;len_of_memdesc_mapped_buf</span><span class="HovzfPYjjR-c1">)</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The exploit calls two </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span>&nbsp;methods; </span><span class="HovzfPYjjR-c7">7</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">19</span><span>. 7 is fairly simple and seems to just be used to put controlled data in a known location. 19 is the buggy one. From the log strings we can tell that block type 19 handler is implemented in a file called </span><span class="HovzfPYjjR-c7">UniformityCompensator.cpp</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://www.benq.com/en-us/knowledge-center/knowledge/screen-uniformity.html">Uniformity Compensation</a></span><span>&nbsp;is a way to correct for inconsistencies in brightness and colour reproduction across a display panel. Block type 19 sets and gets a data structure containing this correction information. The </span><span class="HovzfPYjjR-c7">setBlock_Impl</span><span>&nbsp;method calls </span><span class="HovzfPYjjR-c7">UniformityCompensator::set</span><span>&nbsp;and reaches the following code snippet where </span><span class="HovzfPYjjR-c7">controlled_size</span><span>&nbsp;is a fully-controlled u32 value read from the structure input and </span><span class="HovzfPYjjR-c7">indirect_buffer_ptr</span><span>&nbsp;points to the mapped buffer, the contents of which are also controlled:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2"></span></p><a id="t.7beb7cf889ce845693bd09783570df3d7b3034d3"></a><a id="t.28"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">uint8_t</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;pages </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;compensator</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">inline_buffer</span><span class="HovzfPYjjR-c1">;</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c30">// +0x24</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">for</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;pg_cnt </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">;</span><span class="HovzfPYjjR-c0">&nbsp;pg_cnt </span><span class="HovzfPYjjR-c1">&lt;</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">3</span><span class="HovzfPYjjR-c1">;</span><span class="HovzfPYjjR-c0">&nbsp;pg_cnt</span><span class="HovzfPYjjR-c1">++)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; uint8_t</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;this_page </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;pages</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c9">for</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c9">int</span><span class="HovzfPYjjR-c0">&nbsp;i </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0</span><span class="HovzfPYjjR-c1">;</span><span class="HovzfPYjjR-c0">&nbsp;i </span><span class="HovzfPYjjR-c1">&lt;</span><span class="HovzfPYjjR-c0">&nbsp;controlled_size</span><span class="HovzfPYjjR-c1">;</span><span class="HovzfPYjjR-c0">&nbsp;i</span><span class="HovzfPYjjR-c1">++)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">{</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; memcpy</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c0">this_page</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;indirect_buffer_ptr</span><span class="HovzfPYjjR-c1">,</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">4</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;controlled_size</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; indirect_buffer_ptr </span><span class="HovzfPYjjR-c1">+=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">4</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*</span><span class="HovzfPYjjR-c0">&nbsp;controlled_size</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; &nbsp; this_page </span><span class="HovzfPYjjR-c1">+=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x100</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">}</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; pages </span><span class="HovzfPYjjR-c1">+=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">0x4000</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">}</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c6 HovzfPYjjR-c2"></span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>There's a distinct lack of bounds checking on </span><span class="HovzfPYjjR-c7">controlled_size</span><span>. Based on the structure of the code it looks like it should be restricted to be less than or equal to </span><span class="HovzfPYjjR-c7">64</span><span>&nbsp;(as that would result in the input being completely copied to the output buffer.) The </span><span class="HovzfPYjjR-c7">compensator-&gt;inline_buffer</span><span>&nbsp;buffer is inline in the compensator object. The structure of the code makes it look that that buffer is probably </span><span class="HovzfPYjjR-c7">0xc000</span><span>&nbsp;(three 16k pages) large. To verify this we need to find the allocation site of this compensator object.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>It's read from the </span><span class="HovzfPYjjR-c7">pipe_parent</span><span>&nbsp;object and we know that at this point </span><span class="HovzfPYjjR-c7">pipe_parent</span><span>&nbsp;is a </span><span class="HovzfPYjjR-c7">UPPipeDCP_H13P</span><span>&nbsp;object.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>There's only one write to that field, here in </span><span class="HovzfPYjjR-c7">UPPipeDCP_H13P::setup_tunables_base_target</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.76bc35a503bf64e16502962e6e6a4632f74fe58f"></a><a id="t.29"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">compensator </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c14">CXXnew</span><span class="HovzfPYjjR-c1">(</span><span class="HovzfPYjjR-c4">0xC608LL</span><span class="HovzfPYjjR-c1">);</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c1">...</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c9">this</span><span class="HovzfPYjjR-c1">-&gt;</span><span class="HovzfPYjjR-c0">compensator </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;compensator</span><span class="HovzfPYjjR-c1">;</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The compensator object is a </span><span class="HovzfPYjjR-c7">0xc608</span><span>&nbsp;byte allocation; the </span><span class="HovzfPYjjR-c7">0xc000</span><span>&nbsp;sized buffer starts at offset </span><span class="HovzfPYjjR-c7">0x24</span><span>&nbsp;so the allocation has enough space for </span><span class="HovzfPYjjR-c7">0xc608-0x24=0xC5E4</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;bytes before corrupting neighbouring objects.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The structure input provided by the exploit for the block handler 19 </span><span class="HovzfPYjjR-c7">setBlock</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;call looks like this:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.ab31ebe17a793d09fa94c11be61a4134ecf08386"></a><a id="t.30"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">struct_input_for_block_handler_19</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">0x5F4</span><span class="HovzfPYjjR-c1">]</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">70</span><span class="HovzfPYjjR-c1">;</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c30">// controlled_size</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">struct_input_for_block_handler_19</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">0x5F8</span><span class="HovzfPYjjR-c1">]</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;address</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">struct_input_for_block_handler_19</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">0x600</span><span class="HovzfPYjjR-c1">]</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;a_size</span><span class="HovzfPYjjR-c1">;</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>This leads to a value of 70 (0x46) for </span><span class="HovzfPYjjR-c7">controlled_size</span><span>&nbsp;in the </span><span class="HovzfPYjjR-c7">UniformityCompensator::set</span><span>&nbsp;snippet shown earlier. (</span><span class="HovzfPYjjR-c7">0x5f8</span><span>&nbsp;and </span><span class="HovzfPYjjR-c7">0x600</span><span>&nbsp;correspond to the offsets we saw earlier in the subtype's table: &nbsp;</span><span class="HovzfPYjjR-c7">&lt;2, 0, 0x5F8, 0x600&gt;)</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The inner loop increments the destination pointer by </span><span class="HovzfPYjjR-c7">0x100</span><span>&nbsp;each iteration so </span><span class="HovzfPYjjR-c7">0x46</span><span>&nbsp;loop iterations will write </span><span class="HovzfPYjjR-c7">0x4618</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;bytes.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The outer loop writes to three subsequent </span><span class="HovzfPYjjR-c7">0x4000</span><span>&nbsp;byte blocks so the third (final) iteration starts writing at </span><span class="HovzfPYjjR-c7">0x24 + 0x8000</span><span>&nbsp;and writes a total of </span><span class="HovzfPYjjR-c7">0x4618</span><span>&nbsp;bytes, meaning the object would need to be </span><span class="HovzfPYjjR-c7">0xC63C</span><span>&nbsp;bytes; but we can see that it's only </span><span class="HovzfPYjjR-c7">0xc608</span><span>, meaning that it will overflow the allocation size by </span><span class="HovzfPYjjR-c7">0x34</span><span>&nbsp;bytes. The RTKit malloc implementation looks like it adds 8 bytes of metadata to each allocation so the next object starts at </span><span class="HovzfPYjjR-c7">0xc610</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>How much input is consumed? The input is fully consumed with no "rewinding" so it's </span><span class="HovzfPYjjR-c7">3*0x46*0x46*4 = 0xe5b0</span><span>&nbsp;bytes. Working backwards from the end of that buffer we know that the final </span><span class="HovzfPYjjR-c7">0x34</span><span>&nbsp;bytes of it go off the end of the </span><span class="HovzfPYjjR-c7">0xc608</span><span>&nbsp;allocation which means </span><span class="HovzfPYjjR-c7">+0xe57c</span><span>&nbsp;in the input buffer will be the first byte which corrupts the </span><span class="HovzfPYjjR-c7">8</span><span>&nbsp;metadata bytes and </span><span class="HovzfPYjjR-c7">+0x8584</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;will be the first byte to corrupt the next object:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTc6JqgJIYvcwLtg14PNyjGRL4ds-1hzVvPPYmuSbJ3TiMHTXI3loB4Ib4caBv06WwUAa2H3eEldnlVKePnyUDTxYy6-W0VyMbVSn1YrcilcuOmjeYPwzdQ0ONiWlZbc34oZBXv6hftbOK57Qu_NupLfhgI-Iqc9U51KfJVF5YRk4YmBFcYdoaH27q/s1888/Screenshot%202022-06-22%20at%2016.54.15.png" style="display: block; padding: 1em 0; text-align: center;"><img alt="A diagram showing that the end of the overflower object overlaps with the metadata and start of the target object." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTc6JqgJIYvcwLtg14PNyjGRL4ds-1hzVvPPYmuSbJ3TiMHTXI3loB4Ib4caBv06WwUAa2H3eEldnlVKePnyUDTxYy6-W0VyMbVSn1YrcilcuOmjeYPwzdQ0ONiWlZbc34oZBXv6hftbOK57Qu_NupLfhgI-Iqc9U51KfJVF5YRk4YmBFcYdoaH27q/s1200/Screenshot%202022-06-22%20at%2016.54.15.png" style="max-height: 750; max-width: 600px;" title="A diagram showing that the end of the overflower object overlaps with the metadata and start of the target object." /></a></span></p> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">This matches up exactly with the overflow object which the exploit builds:</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br><a id="t.87397a57c7bdef65de5578925dd0ccccbdee255a"></a><a id="t.31"></a><table class="HovzfPYjjR-c20"><tr class="HovzfPYjjR-c18"><td class="HovzfPYjjR-c13" colspan="1" rowspan="1"> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; v24 </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;address </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c23">0xE584</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; v25 </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_DWORD </span><span class="HovzfPYjjR-c1">*)&amp;</span><span class="HovzfPYjjR-c0">v54</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">48</span><span class="HovzfPYjjR-c1">];</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; v26 </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_OWORD </span><span class="HovzfPYjjR-c1">*)&amp;</span><span class="HovzfPYjjR-c0">v54</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">32</span><span class="HovzfPYjjR-c1">];</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; v27 </span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_OWORD </span><span class="HovzfPYjjR-c1">*)&amp;</span><span class="HovzfPYjjR-c0">v54</span><span class="HovzfPYjjR-c1">[</span><span class="HovzfPYjjR-c4">16</span><span class="HovzfPYjjR-c1">];</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_OWORD </span><span class="HovzfPYjjR-c1">*)(</span><span class="HovzfPYjjR-c0">address </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c23">0xE584</span><span class="HovzfPYjjR-c1">)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_OWORD </span><span class="HovzfPYjjR-c1">*)</span><span class="HovzfPYjjR-c0">v54</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_OWORD </span><span class="HovzfPYjjR-c1">*)(</span><span class="HovzfPYjjR-c0">v24 </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">16</span><span class="HovzfPYjjR-c1">)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;v27</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_OWORD </span><span class="HovzfPYjjR-c1">*)(</span><span class="HovzfPYjjR-c0">v24 </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">32</span><span class="HovzfPYjjR-c1">)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;v26</span><span class="HovzfPYjjR-c1">;</span></p> <p class="HovzfPYjjR-c3"><span class="HovzfPYjjR-c0">&nbsp; </span><span class="HovzfPYjjR-c1">*(</span><span class="HovzfPYjjR-c0">_DWORD </span><span class="HovzfPYjjR-c1">*)(</span><span class="HovzfPYjjR-c0">v24 </span><span class="HovzfPYjjR-c1">+</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c4">48</span><span class="HovzfPYjjR-c1">)</span><span class="HovzfPYjjR-c0">&nbsp;</span><span class="HovzfPYjjR-c1">=</span><span class="HovzfPYjjR-c0">&nbsp;v25</span><span class="HovzfPYjjR-c1">;</span></p></td></tr></table> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The destination object seems to be allocated very early and the DCP RTKit environment appears to be very deterministic with no ASLR. Almost certainly they are attempting to corrupt a neighbouring C++ object with a fake vtable pointer.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>Unfortunately for our analysis the trail goes cold here and we can't fully recreate the rest of the exploit. The bytes for the fake DCP C++ object are read from a file in the app's temporary directory (</span><span>base64 encoded inside a JSON file under the </span><span class="HovzfPYjjR-c7">exploit_struct_offsets</span><span>&nbsp;key</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">) and I don't have a copy of that file. But based on the flow of the rest of the exploit it's pretty clear what happens next:</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.wtkqcqujjnsf"><span>sudo make me </span><span>a</span><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">&nbsp;DART mapping</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>The DCP, like other coprocessors on iPhone, sits behind a DART (Device Address Resolution Table.) This is like an SMMU (IOMMU in the x86 world) which forces an extra layer of physical address lookup between the DCP and physical memory. </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://googleprojectzero.blogspot.com/2017/10/over-air-vol-2-pt-3-exploiting-wi-fi.html">DART was covered in great detail in Gal Beniamini's Over The Air - Vol. 2, Pt. 3 blog post</a></span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The DCP clearly needs to access lots of buffers owned by userspace tasks as well as memory managed by the kernel. To do this the DCP makes RPC calls back to the AP which modifies the DART entries accordingly. This appears to be exactly what the DCP exploit does: the D45X family of DCP-&gt;AP RPC methods appear to expose an interface for requesting arbitrary physical as well as virtual addresses to be mapped into the DCP DART.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">The fake C++ object is most likely a stub which makes such calls on behalf of the exploit, allowing the exploit to read and write kernel memory.</span></p><h2 class="HovzfPYjjR-c15 HovzfPYjjR-c8" id="h.gkcey04fmfci"><span class="HovzfPYjjR-c16 HovzfPYjjR-c2">Conclusions</span></h2> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Segmentation and isolation are in general a positive thing when it comes to security. However, splitting up an existing system into separate, intercommunicating parts can end up exposing unexpected code in unexpected ways.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>We've had discussions within Project Zero about whether this DCP vulnerability is interesting at all. After all, if the </span><span class="HovzfPYjjR-c7">UniformityCompensator</span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;code was going to be running on the Application Processors anyway then the Display Co-Processor didn't really introduce or cause this bug.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Whilst that's true, it's also the case that the DCP certainly made exploitation of this bug significantly easier and more reliable than it would have been on the AP. Apple has invested heavily in memory corruption mitigations over the last few years, so moving an attack surface from a "mitigation heavy" environment to a "mitigation light" one is a regression in that sense.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">Another perspective is that the DCP just isn't isolated enough; perhaps the intention was to try to isolate the code on the DCP such that even if it's compromised it's limited in the effect it could have on the entire system. For example, there might be models where the DCP to AP RPC interface is much more restricted.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">But again there's a tradeoff: the more restrictive the RPC API, the more the DCP code has to be refactored - a significant investment. Currently, the codebase relies on being able to map arbitrary memory and the API involves passing userspace pointers back and forth.</span></p> <p class="c3 c8 c10"><span class="HovzfPYjjR-c5 HovzfPYjjR-c2"></span></p><br> <p class="HovzfPYjjR-c3 HovzfPYjjR-c8"><span>I've discussed in recent posts how attackers tend to be ahead of the curve. As the curve slowly shifts towards memory corruption exploitation getting more expensive, attackers are likely shifting too. We saw that in the </span><span class="HovzfPYjjR-c17"><a class="HovzfPYjjR-c191" href="https://googleprojectzero.blogspot.com/2022/03/forcedentry-sandbox-escape.html">logic-bug sandbox escape used by NSO</a></span><span class="HovzfPYjjR-c5 HovzfPYjjR-c2">&nbsp;and we see that here in this memory-corruption-based privilege escalation that side-stepped kernel mitigations by corrupting memory on a co-processor instead. Both are quite likely to continue working in some form in a post-memory tagging world. Both reveal the stunning depth of attack surface available to the motivated attacker. And both show that defensive security research still has a lot of work to do.</span></p></body> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://www.blogger.com/profile/08975904405228580347' itemprop='url'/> <a class='g-profile' href='https://www.blogger.com/profile/08975904405228580347' rel='author' title='author profile'> <span itemprop='name'>Google Project Zero</span> </a> </span> </span> <span class='post-timestamp'> at <meta content='https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html' itemprop='url'/> <a class='timestamp-link' href='https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2022-06-23T09:01:00-07:00'>9:01&#8239;AM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html#comment-form' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1053444070'> <a href='https://www.blogger.com/post-edit.g?blogID=4838136820032157985&postID=5973748726134682294&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=5973748726134682294&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=5973748726134682294&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=5973748726134682294&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=5973748726134682294&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=4838136820032157985&postID=5973748726134682294&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='https://googleprojectzero.blogspot.com/search?updated-max=2022-10-27T12:48:00-07:00&amp;max-results=1&amp;reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://googleprojectzero.blogspot.com/search?updated-max=2022-06-23T09:01:00-07:00&amp;max-results=1' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='https://googleprojectzero.blogspot.com/'>Home</a> </div> <div class='clear'></div> <div class='blog-feeds'> <div class='feed-links'> Subscribe to: <a class='feed-link' href='https://googleprojectzero.blogspot.com/feeds/posts/default' target='_blank' type='application/atom+xml'>Posts (Atom)</a> </div> </div> </div></div> </div> </div> <div class='column-left-outer'> <div class='column-left-inner'> <aside> </aside> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget BlogSearch' data-version='1' id='BlogSearch1'> <h2 class='title'>Search This Blog</h2> <div class='widget-content'> <div id='BlogSearch1_form'> <form action='https://googleprojectzero.blogspot.com/search' class='gsc-search-box' target='_top'> <table cellpadding='0' cellspacing='0' class='gsc-search-box'> <tbody> <tr> <td class='gsc-input'> <input autocomplete='off' class='gsc-input' name='q' size='10' title='search' type='text' value=''/> </td> <td class='gsc-search-button'> <input class='gsc-search-button' title='search' type='submit' value='Search'/> </td> </tr> </tbody> </table> </form> </div> </div> <div class='clear'></div> </div><div class='widget PageList' data-version='1' id='PageList1'> <h2>Pages</h2> <div class='widget-content'> <ul> <li> <a href='https://googleprojectzero.blogspot.com/p/about-project-zero.html'>About Project Zero</a> </li> <li> <a href='https://googleprojectzero.blogspot.com/p/working-at-project-zero.html'>Working at Project Zero</a> </li> <li> <a href='https://googleprojectzero.blogspot.com/p/0day.html'>0day "In the Wild"</a> </li> <li> <a href='https://googleprojectzero.github.io/0days-in-the-wild/rca.html'>0day Exploit Root Cause Analyses</a> </li> <li> <a href='https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-faq.html'>Vulnerability Disclosure FAQ</a> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Archives</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2025/'> 2025 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2025/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/12/'> December </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2024/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/08/'> August </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2023/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/'> 2022 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> <ul class='posts'> <li><a href='https://googleprojectzero.blogspot.com/2022/06/2022-0-day-in-wild-exploitationso-far.html'>2022 0-day In-the-Wild Exploitation&#8230;so far</a></li> <li><a href='https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html'>The curious tale of a fake Carrier.app</a></li> <li><a href='https://googleprojectzero.blogspot.com/2022/06/an-autopsy-on-zombie-in-wild-0-day.html'>An Autopsy on a Zombie In-the-Wild 0-day</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2022/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2021/01/'> January </a> <span class='post-count' dir='ltr'>(10)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(36)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/08/'> August </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/07/'> July </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2020/01/'> January </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(27)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/08/'> August </a> <span class='post-count' dir='ltr'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2019/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/12/'> December </a> <span class='post-count' dir='ltr'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/10/'> October </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/08/'> August </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2018/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(19)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/04/'> April </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2017/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(33)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/08/'> August </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/07/'> July </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/06/'> June </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2015/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://googleprojectzero.blogspot.com/2014/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> </div> </div> <script type='text/javascript'> //<![CDATA[ (function(){ let archive_list = document.getElementById('ArchiveList'); if (archive_list == null) return; let cur_year = archive_list.querySelector('.post-count-link').innerText.trim() - 0; let last_year = 2014; let elements = []; const MONTHS = ',Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','); let parent = document.getElementById('ArchiveList'); while (parent.childNodes.length) parent.removeChild(parent.childNodes[0]); function fetch_next_year() { let url = 'https://googleprojectzero.blogspot.com/?action=getTitles&widgetId=BlogArchive1&widgetType=BlogArchive&responseType=js&path=https%3A%2F%2Fgoogleprojectzero.blogspot.com%2F'+cur_year; fetch(url).then(resp => { if (!resp.ok) { console.log('http error'); return; } resp.text().then(text => { let scope = { _WidgetManager: { _HandleControllerResult: (name, method, results) => { elements.push(document.createElement('hr')); let year_header = document.createElement('div'); year_header.appendChild(document.createTextNode(cur_year)); year_header.style.fontSize = 'large'; elements.push(year_header); let list = document.createElement('ul'); elements.push(list); for (let obj of results.posts) { let link_parts = obj.url.split('/'); let year = link_parts[3]; let month = link_parts[4]; let el = document.createElement(/*'div'*/'li'); el.style.listStyleType = 'square'; el.style.listStylePosition = 'inside'; let link = document.createElement('a'); el.appendChild(link); link.appendChild(document.createTextNode(obj.title)); link.href = obj.url; let date_trailer = document.createElement('span'); el.appendChild(date_trailer); //date_trailer.appendChild(document.createTextNode(' ('+year+'-'+month+')')); date_trailer.appendChild(document.createTextNode(' ('+MONTHS[parseInt(month, 10)]+')')); //date_trailer.style.textAlign = 'right'; //elements.push(el); list.appendChild(el); } } } }; with (scope) { eval(text); } if (cur_year == last_year) { finish(); } else { cur_year--; fetch_next_year(); } }); }); } fetch_next_year(); function finish() { for (let obj of elements) { parent.appendChild(obj); } console.log(elements); } })(); //]]> </script> <div class='clear'></div> </div> </div></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='sidebar no-items section' id='sidebar-right-2-1'></div> </td> <td class='columns-cell'> <div class='sidebar no-items section' id='sidebar-right-2-2'></div> </td> </tr> </tbody> </table> <div class='sidebar no-items section' id='sidebar-right-3'></div> </aside> </div> </div> </div> <div style='clear: both'></div> <!-- columns --> </div> <!-- main --> </div> </div> <div class='main-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <footer> <div class='footer-outer'> <div class='footer-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left footer-fauxborder-left'> <div class='fauxborder-right footer-fauxborder-right'></div> <div class='region-inner footer-inner'> <div class='foot no-items section' id='footer-1'></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='foot no-items section' id='footer-2-1'></div> </td> <td class='columns-cell'> <div class='foot no-items section' id='footer-2-2'></div> </td> </tr> </tbody> </table> <!-- outside of the include in order to lock Attribution widget --> <div class='foot section' id='footer-3' name='Footer'><div class='widget Attribution' data-version='1' id='Attribution1'> <div class='widget-content' style='text-align: center;'> Powered by <a href='https://www.blogger.com' target='_blank'>Blogger</a>. </div> <div class='clear'></div> </div></div> </div> </div> <div class='footer-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </footer> <!-- content --> </div> </div> <div class='content-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <script type='text/javascript'> window.setTimeout(function() { document.body.className = document.body.className.replace('loading', ''); }, 10); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/1704033933-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY7umr29N5ULdQt8WWDpXFYgLt22Sg:1740164165213';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d4838136820032157985','//googleprojectzero.blogspot.com/2022/06/','4838136820032157985'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '4838136820032157985', 'title': 'Project Zero', 'url': 'https://googleprojectzero.blogspot.com/2022/06/', 'canonicalUrl': 'https://googleprojectzero.blogspot.com/2022/06/', 'homepageUrl': 'https://googleprojectzero.blogspot.com/', 'searchUrl': 'https://googleprojectzero.blogspot.com/search', 'canonicalHomepageUrl': 'https://googleprojectzero.blogspot.com/', 'blogspotFaviconUrl': 'https://googleprojectzero.blogspot.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': false, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-240546891-1', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Project Zero - Atom\x22 href\x3d\x22https://googleprojectzero.blogspot.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Project Zero - RSS\x22 href\x3d\x22https://googleprojectzero.blogspot.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Project Zero - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/4838136820032157985/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/c320e3f9c6626331', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': 'June 2022', 'pageTitle': 'Project Zero: June 2022'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Project Zero', 'description': 'News and updates from the Project Zero team at Google', 'url': 'https://googleprojectzero.blogspot.com/2022/06/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2022, 'month': 6, 'rangeMessage': 'Showing posts from June, 2022'}}}]); _WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', document.getElementById('Navbar1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/2332438401-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/1964470060-lightbox_bundle.css'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogSearchView', new _WidgetInfo('BlogSearch1', 'sidebar-right-1', document.getElementById('BlogSearch1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PageListView', new _WidgetInfo('PageList1', 'sidebar-right-1', document.getElementById('PageList1'), {'title': 'Pages', 'links': [{'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/about-project-zero.html', 'id': '4384467920505278144', 'title': 'About Project Zero'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/working-at-project-zero.html', 'id': '2459334498880008057', 'title': 'Working at Project Zero'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/0day.html', 'id': '3414239791814532209', 'title': '0day \x22In the Wild\x22'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.github.io/0days-in-the-wild/rca.html', 'title': '0day Exploit Root Cause Analyses'}, {'isCurrentPage': false, 'href': 'https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-faq.html', 'id': '2935252455704572784', 'title': 'Vulnerability Disclosure FAQ'}], 'mobile': false, 'showPlaceholder': true, 'hasCurrentPage': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', document.getElementById('Attribution1'), {}, 'displayModeFull')); </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10