<div dir="ltr">Hi Aman,<div>For `-verbose:class`, it's a JVM argument instead of a program argument; so when you run a java program like `java Main`, you should call it as `java -verbose:class Main`.</div><div>When done correctly, you should see hidden class outputs like:</div><div>[0.032s][info][class,load] java.lang.invoke.LambdaForm$MH/0x00000200cc000400 source: __JVM_LookupDefineClass__<br></div><div>The loading of java.lang.invoke hidden classes requires your program to use MethodHandle features, like a lambda.</div><div><br></div><div>I think the problem you are exploring, that to avoid dynamic class loading and effectively turn Java Platform closed for security, is also being accomplished by project Leyden (as I've shared initially); Thus, I am forwarding this to leyden-dev instead, so you can see what approach Leyden uses to accomplish the same goal as yours.</div><div><br></div><div>Regards, Chen Liang</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, May 17, 2024 at 4:40 AM Aman Sharma <<a href="mailto:amansha@kth.se">amansha@kth.se</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>
<div>
<div id="m_-6689849625419728689divtagdefaultwrapper" style="font-size:12pt;color:rgb(0,0,0);font-family:Garamond,Georgia,serif" dir="ltr">
<p>Hi Roger,</p>
<p><br>
</p>
<p>Do you have ideas on how to intercept them? My javaagent is not able to nor a JVMTI agent passed using `agentpath` option. It also does not seem to show up in logs when I pass `-verbose:class`.</p>
<p><br>
</p>
<p>Also, what do you think of renaming the proxy classes as suggested below?<br>
</p>
<p><br>
</p>
<div id="m_-6689849625419728689Signature">
<div id="m_-6689849625419728689divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div id="m_-6689849625419728689m_4935352394101912768Signature">
<div name="divtagdefaultwrapper"><font size="2" color="#808080"><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"><span id="m_-6689849625419728689divtagdefaultwrapper" style="font-size:12pt">
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">Regards,</span></div>
<span style="font-family:Garamond,Georgia,serif"></span><span style="font-family:Garamond,Georgia,serif"></span><span style="color:rgb(0,0,0)"></span><span style="font-family:Garamond,Georgia,serif"></span><span style="font-family:Garamond,Georgia,serif"></span>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">Aman Sharma</span></div>
</span><br>
</span></font></div>
<div name="divtagdefaultwrapper"><font size="2" color="#808080"><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"></span><span>PhD Student<br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">KTH Royal Institute of Technology</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
</span><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">School of Electrical Engineering and Computer Science (EECS)</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">Department of Theoretical Computer Science (TCS)</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"><a href="http://www.kth.se" id="m_-6689849625419728689LPNoLP" target="_blank"></a><a href="https://www.kth.se/profile/amansha" id="m_-6689849625419728689LPNoLP" target="_blank"></a><a href="https://www.kth.se/profile/amansha" id="m_-6689849625419728689LPNoLP" target="_blank"></a></span></font></div>
</div>
<a href="https://www.kth.se/profile/amansha" id="m_-6689849625419728689LPNoLP" target="_blank"><span style="font-size:10pt"></span></a><a href="https://algomaster99.github.io/" id="m_-6689849625419728689LPNoLP" target="_blank">https://algomaster99.github.io/</a><br>
</div>
</div>
</div>
<hr style="display:inline-block;width:98%">
<div id="m_-6689849625419728689divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> core-libs-dev <<a href="mailto:core-libs-dev-retn@openjdk.org" target="_blank">core-libs-dev-retn@openjdk.org</a>> on behalf of Roger Riggs <<a href="mailto:roger.riggs@oracle.com" target="_blank">roger.riggs@oracle.com</a>><br>
<b>Sent:</b> Friday, May 17, 2024 4:57:46 AM<br>
<b>To:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a><br>
<b>Subject:</b> Re: Deterministic naming of subclasses of `java/lang/reflect/Proxy`</font>
<div> </div>
</div>
<div>Hi Aman,<br>
<br>
You may also run into hidden classes (JEP 371: Hidden Classes) that allow classes to be defined, at runtime, without names.<br>
It has been proposed to use them for generated proxies but that hasn't been implemented yet.<br>
There are benefits to having nameless classes, because they can't be referenced by name, only as a capability, they can be better encapsulated.<br>
<br>
fyi, Roger Riggs<br>
<br>
<br>
<div>On 5/16/24 8:11 AM, Aman Sharma wrote:<br>
</div>
<blockquote type="cite">
<div id="m_-6689849625419728689divtagdefaultwrapper" style="font-size:12pt;color:rgb(0,0,0);font-family:Garamond,Georgia,serif" dir="ltr">
<div id="m_-6689849625419728689divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Garamond,Georgia,serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<p>Hi,</p>
<p><br>
</p>
<p>Thanks for your response, Liang!</p>
<p><br>
</p>
<p>> <span>I think you meant CVE-2021-42392 instead of 2022.</span></p>
<p><br>
</p>
<p>Sorry of the error. I indeed meant <a href="https://nvd.nist.gov/vuln/detail/cve-2021-42392" target="_blank">
<span>CVE-2021-42392</span></a>.<br>
</p>
<p><br>
</p>
<p>> <span>Leyden mainly avoids this unstable generation by performing a training run to collect classes loaded</span></p>
<p><br>
</p>
<p>Would love to know the details of Project Leyden and how they worked so far to focus on this goal. In our case, the training run is the test suite.</p>
<p><br>
</p>
<p>> <span>GeneratedConstructorAccessor is already retired by JEP 416 [2] in Java 18</span></p>
<p><br>
</p>
<p>I did see them not appearing in my allowlist when I ran my study subject (Apache PDFBox) with Java 21. Thanks for letting me know about this JEP. I see they are re-implemented with method handles.</p>
<p><br>
</p>
<p>> <span>How are you checking the classes?</span></p>
<p><br>
</p>
<p>To detect runtime generated code, we have javaagent that is hooked statically to the test suite execution. It gives us all classes that that is loaded post the JVM and the javaagent are loaded. So we only check the classes loaded for the purpose of running
the application. This is also why we did not choose -agentlib as it would give classes for the setting up JVM and javaagent and we the user of our tool must the classes they load.</p>
<p><br>
</p>
<p>Next, we have a `<span>ClassFileTransformer</span>` hook in the agent where we produce the checksum using the bytecode. And we compare the checksum with the one existing in the allowlist. The checksum computation algorithm is same for both steps. Let me
describe how I compute the checksum.</p>
<p><br>
</p>
<ol style="margin-bottom:0px;margin-top:0px">
<li>I get the <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.4.1" target="_blank">
CONSTANT_Class_info</a> entry corresponding to `this_class` and rewrite the <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.4.7" target="_blank">
<span>CONSTANT_Utf8_info</span></a> corresponding to a fix String constant, say "foo".
</li><li>Since, the name of the class is used to refer to its types members (fields/method), I get all
<a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.4.2" target="_blank">
<span>CONSTANT_Fieldref_info</span></a> and if its `class_index` corresponds to the old `this_class`, we rewrite the UTF8 value of class_index to the same constant "foo".
</li><li>Next, since the naming of the fields, in Proxy classes, are also suffixed by numbers, for example, `private static Method m4`, we rewrite the UTF8 value of name in the
<a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.4.6" target="_blank">
CONSTANT_NameAndType_info</a>. </li><li>These fields can also have a random order so we simply sort the entire byte code using `Arrays.sort(byte[])` to eliminate any differences due to ordering of fields/methods.
</li><li>Simply sorting the byte array still had minute differences. I could not understand why they existed even though values in constant pool of the bytecode in allowlist and at runtime were exactly the same after rewriting. The differences existed in the bytes
of the Code attribute of methods. I concluded that the bytes stored some position information. To avoid this, I created a subarray where I considered the bytes corresponding to
<span>`<span>CONSTANT_Utf8_info</span>.bytes` only. Computing a checksum for it resulted in the same checksums for both classfiles.</span>
</li></ol>
<div><br>
</div>
<div>Let's understand the whole approach with an example of Proxy class.</div>
<div><br>
</div>
<div>`
<pre class="gmail-notranslate"><span>public</span> <span>final</span> <span>class</span> <span>$Proxy42</span> <span>extends</span> <span>Proxy</span> <span>implements</span> <span>org.apache.logging.log4j.core.config.plugins</span>.<span>Plugin</span> {</pre>
`</div>
<div><br>
</div>
<div>The will go in the allowlist as "Proxy_Plugin: <SHA256 checksum>". <br>
</div>
<div><br>
</div>
<div>When the same class is intercepted at runtime, say "$Proxy10", we look for "Proxy_Plugin" in the allowlist and since the checksum algorithm is same in both cases, we get a match and let the class load.<br>
</div>
<div><br>
</div>
<div>This approach has seemed to work well for Proxy classes, Generated Constructor Accessor (which is removed as you said). I also looked at the species generated by method handles. I did not notice any modification in them. Their name generation seemed okay
to me. If some new Species are generated, it is of course detected since it is not in the allowlist.</div>
<div><br>
</div>
<div>I have not looked into LambdaMetafactory because I did not encounter it as a problem so far, but I am aware its name generation is also unstable. I have run my approach only a few projects only. And for hidden classes, I assume the the agent won't be able
to intercept them so detecting them would be really hard.<br>
</div>
<p><br>
</p>
<div id="m_-6689849625419728689Signature">
<div id="m_-6689849625419728689divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div id="m_-6689849625419728689m_4935352394101912768Signature">
<div name="divtagdefaultwrapper"><font size="2" color="#808080"><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"><span id="m_-6689849625419728689divtagdefaultwrapper" style="font-size:12pt">
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">Regards,</span></div>
<span style="font-family:Garamond,Georgia,serif"></span><span style="font-family:Garamond,Georgia,serif"></span><span style="color:rgb(0,0,0)"></span><span style="font-family:Garamond,Georgia,serif"></span><span style="font-family:Garamond,Georgia,serif"></span>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">Aman Sharma</span></div>
</span><br>
</span></font></div>
<div name="divtagdefaultwrapper"><font size="2" color="#808080"><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"></span><span>PhD Student<br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">KTH Royal Institute of Technology</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
</span><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">School of Electrical Engineering and Computer Science (EECS)</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">Department of Theoretical Computer Science (TCS)</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"></span></font></div>
</div>
<a href="https://www.kth.se/profile/amansha" id="m_-6689849625419728689LPNoLP" target="_blank"><span style="font-size:10pt"></span></a><a href="https://algomaster99.github.io/" id="m_-6689849625419728689LPNoLP" target="_blank">https://algomaster99.github.io/</a><br>
</div>
</div>
</div>
<hr style="display:inline-block;width:98%">
<div id="m_-6689849625419728689divRplyFwdMsg" dir="ltr"><font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b>
<a href="mailto:liangchenblue@gmail.com" target="_blank">liangchenblue@gmail.com</a>
<a href="mailto:liangchenblue@gmail.com" target="_blank"><liangchenblue@gmail.com></a><br>
<b>Sent:</b> Thursday, May 16, 2024 5:52:03 AM<br>
<b>To:</b> Aman Sharma; core-libs-dev<br>
<b>Cc:</b> Martin Monperrus<br>
<b>Subject:</b> Re: Deterministic naming of subclasses of `java/lang/reflect/Proxy`</font>
<div> </div>
</div>
<div>
<div dir="ltr">Hi Aman,
<div>I think you meant CVE-2021-42392 instead of 2022.</div>
<div><br>
<div>For your approach of an "allowlist" for Java runtime, project Leyden is looking to generate a static image [1], that </div>
<div>> At run time it cannot load classes from outside the image, nor can it create classes dynamically.</div>
<div>Leyden mainly avoids this unstable generation by performing a training run to collect classes loaded and even object graphs; I am not familiar with the details unfortunately.</div>
<div><br>
</div>
<div>Otherwise, the Proxy discussion belongs better to core-libs-dev, as java.lang.reflect.Proxy is part of Java's core libraries. I am replying this thread to core-libs-dev.</div>
<div><br>
</div>
<div>For your perceived problem that classes don't have unique names, your description sounds dubious: GeneratedConstructorAccessor is already retired by JEP 416 [2] in Java 18, and there are many other cases in which JDK generates classes without stable names,
notoriously LambdaMetafactory (Gradle wished for cacheable Lambdas); the same applies for the generated classes for MethodHandle's LambdaForms (which carries implementation code for LambdaForm). How are you checking the classes? It seems you are not checking
hidden classes. Proxy and Lambda classes are defined by the caller's class loader, while LambdaForms are under JDK's system class loader I think. We need to ensure you are correctly finding all unstable classes before we can proceed.</div>
<div><br>
</div>
<div>[1]: <a href="https://openjdk.org/projects/leyden/notes/01-beginnings" target="_blank">https://openjdk.org/projects/leyden/notes/01-beginnings</a></div>
<div>[2]: <a href="https://openjdk.org/jeps/416" target="_blank">
https://openjdk.org/jeps/416</a><br>
</div>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Wed, May 15, 2024 at 7:00 PM Aman Sharma <<a href="mailto:amansha@kth.se" target="_blank">amansha@kth.se</a>> wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="ltr">
<div id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Garamond,Georgia,serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<p>Hi,</p>
<p><br>
</p>
<p>My name is Aman and I am a PhD student at KTH Royal Institute of Technology, Stockholm, Sweden. I research as part of
<a href="https://chains.proj.kth.se/" target="_blank">CHAINS</a> project to strengthen the software supply chain of multiple ecosystem. I particularly focus on runtime integrity in Java. In this email, I want to write about an issue I
have discovered with <i>dynamic generation of `java.lang.reflect.Proxy`classes</i>. I will propose a solution and would love to hear the feedback from the community. Let me know if this is the correct mailing-list for such discussions. It seemed the most relevant
from <a href="https://mail.openjdk.org/mailman/listinfo" target="_blank">
this list</a>.</p>
<p><br>
</p>
<p><b>My research</b></p>
<p><b><br>
</b></p>
<p>Java has features to load class on the fly - it can either download or generate a class at runtime. These features are useful for inner workings of JDK. For example, implementing annotations, reflective access, etc. However, these features have also contributed
to critical vulnerabilities in the past - CVE-2021-44228 (log4shell), CVE-2022-33980, CVE-2022-42392. All of these vulnerabilities have one thing in common -
<i>a class that was not known during build time was downloaded/generated at runtime and loaded into JVM.</i></p>
<p><br>
</p>
<p>To defend against such vulnerabilities, we propose a solution to <i>allowlist classes for runtime</i>. This allowlist will contain an exhaustive list of classes that can be loaded by the JVM and it will be enforced at runtime. We build this allowlist from
three sources:</p>
<ol style="margin-bottom:0px;margin-top:0px">
<li>All classes of all modules provided by the Java Standard Library. We use <a href="https://github.com/classgraph/classgraph" target="_blank">
ClassGraph</a> to scan the JDK. </li><li>We can take the source code and all dependencies of an application. We use a software bill of materials to get all the data.
</li><li>Finally, we use run the test suite to include any runtime downloaded/generated classes.
</li></ol>
<div>Such a list is able to prevent the above 3 CVEs because it does not let the "unknown" bytecode to be loaded.</div>
<div><br>
</div>
<div><b>Problem with generating such an allowlist</b></div>
<div><b><br>
</b></div>
<div>The first two parts of the allowlist are easy to get. The problem is with the third step where we want to allowlist all the classes that could be downloaded or generated. Upon running the test suite and hooking to the classes it loads, we observer that
the list consists of classes that are called "<span>com/sun/proxy/$Proxy2</span>", "<span>jdk/internal/reflect/GeneratedConstructorAccessor3</span>" among many more. The purpose of these classes can be identifed. The proxy class is created for to implement
an annotation. The accessor gives access to constructor of a class to the JVM.</div>
<div><br>
</div>
<div>When enforcing this allowlist at runtime, we see that the bytecode content for "<span>com/sun/proxy/$Proxy2</span>" differs in the allowlist and at runtime. In our case, we we are experimenting with
<a href="https://github.com/apache/pdfbox" target="_blank">
pdfbox</a> so we created the allowlist using its test suite. Then we enforced this allowlist while running some of its subcommands. However, there was some other proxy class say
<span>"com/sun/proxy/$Proxy5" at runtime that implemented the same interfaces and had the same methods as "<span>com/sun/proxy/$Proxy2" in the allowlist. They only differed in the name of the class, order of fields, and types for fields references. This could
happen because the order of the loading of class is workload dependent, but it causes problem to generate such an allowlist.</span></span></div>
<div><span><span><br>
</span></span></div>
<div><span><span><b>Solution <br>
</b></span></span></div>
<p><br>
We propose that naming of subclasses of "<span>java/lang/reflect/Proxy</span>" should not be dependent upon the order of loading. In order to do so, two issues can be fixed:</p>
<ol style="margin-bottom:0px;margin-top:0px">
<li><span><a href="https://github.com/openjdk/jdk/blob/b687aa550837830b38f0f0faa69c353b1e85219c/src/java.base/share/classes/java/lang/reflect/Proxy.java#L531" target="_blank">The naming of the class should not be based on AtomicLong</a></span>.
Rather it could be named based on the interfaces it implements. I also wonder why AtomicLong is chosen in the first place.
</li><li>Methods of the interfaces must be in a particular order. Right now, <span></span><span><span></span></span><a href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Class.java#L2178" target="_blank"><span><span>they
are not sorted in any particular orde</span>r</span></a>.<br>
</li></ol>
<p><br>
</p>
<div id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940Signature">
<div id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<div id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940m_4935352394101912768Signature">
<div name="divtagdefaultwrapper"><font size="2" color="#808080"><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"><span id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940divtagdefaultwrapper" style="font-size:12pt">
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">These fixes will make proxy class generation deterministic with respect to order of loading and won't be flagged at runtime since the test suite
would already detect them.</span></div>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif"><br>
</span></div>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">I would love to hear from the community about these ideas. If in agreement, I would be happy to produce a patch. I have discovered this issue with
subclasses of <a href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/reflect/ConstructorAccessor.java" target="_blank">
GeneratedConstructorAccessor</a> as well and I imagine it will also apply to some other runtime generated classes. If you disagree, please let me know also. It helps with my research.</span></div>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif"><br>
</span></div>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">I also have
<a href="https://github.com/chains-project/exploits-for-sbom.exe" target="_blank">
PoCs for the above CVEs</a> and a proof concept tool is being developed under the name
<a href="https://github.com/chains-project/sbom.exe" target="_blank">
sbom.exe</a> in case any one wonders about the implementation. I would also be happy to explain more.<br>
</span></div>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif"><br>
</span></div>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">Regards,</span></div>
<span style="font-family:Garamond,Georgia,serif"></span><span style="font-family:Garamond,Georgia,serif"></span><span style="color:rgb(0,0,0)"></span><span style="font-family:Garamond,Georgia,serif"></span><span style="font-family:Garamond,Georgia,serif"></span>
<div style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(0,0,0);font-family:Garamond,Georgia,serif">Aman Sharma</span></div>
</span><br>
</span></font></div>
<div name="divtagdefaultwrapper"><font size="2" color="#808080"><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"></span><span>PhD Student<br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">KTH Royal Institute of Technology</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
</span><span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">School of Electrical Engineering and Computer Science (EECS)</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)">Department of Theoretical Computer Science (TCS)</span><br style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif">
<span style="font-family:Arial,"Helvetica Neue",helvetica,sans-serif;background-color:rgb(255,255,255)"></span></font></div>
</div>
<a href="https://www.kth.se/profile/amansha" id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940LPNoLP" target="_blank"><span style="font-size:10pt"></span></a><a href="https://algomaster99.github.io/" id="m_-6689849625419728689m_5381525267202685274m_1510169701429416940LPNoLP" target="_blank">https://algomaster99.github.io/</a><br>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</blockquote>
<br>
</div>
</div>
</blockquote></div>