<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>RazzSec Lab</title><description>Rahul Razz - binary exploitation, reverse engineering, and security research</description><link>https://razz.systems/</link><language>en</language><item><title>Team Nova - CTF Player</title><link>https://razz.systems/posts/experience/team-nova-ctf-player/</link><guid isPermaLink="true">https://razz.systems/posts/experience/team-nova-ctf-player/</guid><description>My current CTF experience with Team Nova, focused on pwn, cryptography, reverse engineering, and firmware security.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Role&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;CTF Player - Part time&lt;/strong&gt;&lt;br /&gt;
Team Nova&lt;br /&gt;
April 2025 - Current&lt;/p&gt;
&lt;h2&gt;Focus&lt;/h2&gt;
&lt;p&gt;I compete in Capture The Flag competitions with Team Nova, mainly working on binary exploitation, cryptography, and reverse engineering.&lt;/p&gt;
&lt;h2&gt;Work&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Solved pwn challenges involving memory corruption, heap exploitation, and File Stream Oriented Programming&lt;/li&gt;
&lt;li&gt;Worked with GDB, pwntools, IDA, Ghidra, and Binary Ninja during exploit development and analysis&lt;/li&gt;
&lt;li&gt;Collaborated with teammates to analyze vulnerabilities, develop exploits, and document attack strategies&lt;/li&gt;
&lt;li&gt;Started firmware reverse engineering work for hardware security assessment&lt;/li&gt;
&lt;li&gt;Studied bootloaders, secure boot mechanisms, and firmware integrity checks&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Collabra AI - AI-Powered Collaborative Code Editor</title><link>https://razz.systems/posts/projects/collabra-ai/</link><guid isPermaLink="true">https://razz.systems/posts/projects/collabra-ai/</guid><description>A real-time collaborative code editor built with React, Tailwind, WebSockets, Firestore, Gemini, WebContainers, Monaco Editor, Yjs, JWT, and Redis.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Collabra AI is an AI-powered collaborative code editor built to make team coding sessions smoother and faster. The project combines real-time editing, chat, cloud storage, AI-assisted code generation, and browser-based build/run support.&lt;/p&gt;
&lt;h2&gt;Key Work&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Built the frontend with &lt;strong&gt;React.js&lt;/strong&gt; and &lt;strong&gt;Tailwind CSS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Engineered real-time chat using &lt;strong&gt;WebSockets&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Used &lt;strong&gt;Firestore&lt;/strong&gt; for codebase storage&lt;/li&gt;
&lt;li&gt;Integrated &lt;strong&gt;Google Gemini 2.5&lt;/strong&gt; for on-demand code generation&lt;/li&gt;
&lt;li&gt;Used &lt;strong&gt;WebContainers&lt;/strong&gt; for optimized in-browser build and run workflows&lt;/li&gt;
&lt;li&gt;Integrated &lt;strong&gt;Monaco Editor&lt;/strong&gt; and &lt;strong&gt;Yjs&lt;/strong&gt; for collaborative editing&lt;/li&gt;
&lt;li&gt;Added debounced logic and lint checks for smoother broadcasting&lt;/li&gt;
&lt;li&gt;Built a scalable &lt;strong&gt;Node.js + Express&lt;/strong&gt; backend&lt;/li&gt;
&lt;li&gt;Implemented &lt;strong&gt;JWT + Redis&lt;/strong&gt; authentication and role-based access control&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Live App&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://collabra-frontend.vercel.app/&quot;&gt;Open Collabra AI&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Minimal Terminal-Based Operating System</title><link>https://razz.systems/posts/projects/minimal-terminal-operating-system/</link><guid isPermaLink="true">https://razz.systems/posts/projects/minimal-terminal-operating-system/</guid><description>A minimal terminal OS for studying virtual memory, process isolation, system calls, paging, and fault handling.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This project is a minimal terminal-based operating system built to study memory management in both kernel and user space.&lt;/p&gt;
&lt;h2&gt;Key Work&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Built a terminal-oriented OS environment&lt;/li&gt;
&lt;li&gt;Implemented virtual memory management&lt;/li&gt;
&lt;li&gt;Added process isolation mechanisms&lt;/li&gt;
&lt;li&gt;Implemented system call interfaces&lt;/li&gt;
&lt;li&gt;Tested memory allocation behavior&lt;/li&gt;
&lt;li&gt;Studied paging and fault handling&lt;/li&gt;
&lt;li&gt;Used the project to understand OS-level memory safety and stability tradeoffs&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Post-Quantum Secure DTLS for RISC-V IoT Systems</title><link>https://razz.systems/posts/projects/post-quantum-secure-dtls-riscv/</link><guid isPermaLink="true">https://razz.systems/posts/projects/post-quantum-secure-dtls-riscv/</guid><description>DTLS 1.3 with post-quantum key exchange for resource-constrained RISC-V IoT systems.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This project explored securing IoT communication by integrating post-quantum cryptographic key exchange into &lt;strong&gt;DTLS 1.3&lt;/strong&gt; and testing it in a constrained RISC-V environment.&lt;/p&gt;
&lt;h2&gt;Key Work&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Implemented &lt;strong&gt;DTLS 1.3&lt;/strong&gt; with post-quantum cryptographic key exchange&lt;/li&gt;
&lt;li&gt;Integrated PQC algorithms into the DTLS handshake&lt;/li&gt;
&lt;li&gt;Evaluated compatibility and performance on resource-constrained systems&lt;/li&gt;
&lt;li&gt;Deployed and tested the implementation on a &lt;strong&gt;RISC-V LiteX-based SoC simulation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Focused on embedded security constraints, protocol behavior, and performance tradeoffs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Result&lt;/h2&gt;
&lt;p&gt;This work contributed to an &lt;strong&gt;Inter IIT Tech Meet 14.0&lt;/strong&gt; project where the team ranked &lt;strong&gt;5th&lt;/strong&gt; in PQC implementation and DTLS protocol work.&lt;/p&gt;
</content:encoded></item><item><title>Start Here: RazzSec Lab</title><link>https://razz.systems/posts/start-here/</link><guid isPermaLink="true">https://razz.systems/posts/start-here/</guid><description>How this site is organized and how to add new CTF writeups or projects.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This site is organized as a personal CTF lab and security notebook.&lt;/p&gt;
&lt;h2&gt;Main Sections&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CTF Writeups:&lt;/strong&gt; full challenge walkthroughs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux:&lt;/strong&gt; enumeration, privilege escalation, shell workflow&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reverse Engineering:&lt;/strong&gt; Ghidra, debugging, binary analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Binary Exploitation:&lt;/strong&gt; stack, ROP, format strings, pwntools&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Security:&lt;/strong&gt; Burp, auth bugs, injection, file upload issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Projects:&lt;/strong&gt; tools, scripts, exploit templates, and security experiments&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Add A New Writeup&lt;/h2&gt;
&lt;p&gt;Create a new Markdown file under &lt;code&gt;src/content/posts/&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pnpm new-post ctf-writeups/my-new-writeup.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then set the frontmatter:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;title: &quot;Challenge Name - Platform&quot;
published: 2026-06-07
description: &quot;One sentence summary.&quot;
tags: [&quot;pwn&quot;, &quot;gdb&quot;, &quot;pwntools&quot;]
category: &quot;CTF Writeups&quot;
draft: false
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Recommended Writeup Structure&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Challenge info&lt;/li&gt;
&lt;li&gt;Recon&lt;/li&gt;
&lt;li&gt;Analysis&lt;/li&gt;
&lt;li&gt;Exploit or solution&lt;/li&gt;
&lt;li&gt;Flag/result&lt;/li&gt;
&lt;li&gt;Lessons learned&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>FSOP: File Stream Oriented Programming</title><link>https://razz.systems/posts/binary-exploitation/fsop-file-stream-oriented-programming/</link><guid isPermaLink="true">https://razz.systems/posts/binary-exploitation/fsop-file-stream-oriented-programming/</guid><description>A beginner-friendly deep dive into FSOP exploitation through glibc FILE structures, _IO_flush_all, _IO_wfile_jumps, and fake wide-data vtables.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I&apos;M going to explain you the  File Stream Oriented Programming &lt;code&gt;FSOP&lt;/code&gt; exploitation in very beginner friendly way , at least i would try.
The motivation for this writeup is due to those friends , who knows very much basic ROP , But afraid of this topic because they think File struct is just an Advance Exploitation and require more details to learn about File Structure of C And mostly they are confused in how FSOP work.
So i am going to explain those low-level details in very raw format . My main focus would be always on the reason of why this is happening rather than what would happen ./?
I would start from the exit() function , because this is the best way to exploit if no other printf, scanf, etc. function is unavailable..&lt;/p&gt;
&lt;p&gt;In this writeup i followed these binary files taken from &lt;code&gt;Securinets CTF&lt;/code&gt; ,:
Challenge file : &lt;a href=&quot;https://github.com/Rahulrajln1111/Writeups/blob/main/FSOP/chall&quot;&gt;chall&lt;/a&gt; #I modified this binary to make it easy to follow&lt;/p&gt;
&lt;p&gt;libc (non-stripped) : &lt;a href=&quot;https://github.com/Rahulrajln1111/Writeups/blob/main/FSOP/libc.so.6&quot;&gt;libc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;linker:&lt;a href=&quot;https://github.com/Rahulrajln1111/Writeups/blob/main/FSOP/ld-linux-x86-64.so.2&quot;&gt;ld&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;detailed exploit:&lt;a href=&quot;https://github.com/Rahulrajln1111/Writeups/blob/main/FSOP/solve.py&quot;&gt;exploit&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;_Start:&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;void
exit (int status)
{
__run_exit_handlers (status, &amp;amp;__exit_funcs, true, true);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;After End of main() function , our program call &lt;code&gt;exit()--&amp;gt;__run_exit_handlers()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1. Inside exit_handlers&lt;/h2&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
bool run_list_atexit, bool run_dtors)
{
...
while (true)
{
...
}
while (cur-&amp;gt;idx &amp;gt; 0)
{
struct exit_function *const f = &amp;amp;cur-&amp;gt;fns[--cur-&amp;gt;idx];
const uint64_t new_exitfn_called = __new_exitfn_called;
switch (f-&amp;gt;flavor)
{
.....

}
....
__libc_lock_unlock (__exit_funcs_lock);
if (run_list_atexit)
call_function_static_weak (_IO_cleanup);//This is our target function to trace for File stream flush operations..
_exit (status);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Full exit.c code : &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.40.9000/source/stdlib/exit.c&quot;&gt;exit.c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;_IO_cleanup() purpose:&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This function is part of glibc’s internal I/O system (libio).&lt;/li&gt;
&lt;li&gt;It is called at program termination (via exit() or similar paths) to:&lt;/li&gt;
&lt;li&gt;flush all open standard I/O streams (stdout, stderr, file streams, etc.)&lt;/li&gt;
&lt;li&gt;Make sure any buffered data is written to files.&lt;/li&gt;
&lt;li&gt;Switch streams to unbuffered mode afterward.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;int
IOcleanup (void)
{
  int result = IOflush_all (); 
  IOunbuffer_all ();
  return result;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt; int result = _IO_flush_all ();&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;calls &lt;code&gt;_IO_flush_all()&lt;/code&gt;, which:&lt;/li&gt;
&lt;li&gt;Iterates over all open FILE* objects.&lt;/li&gt;
&lt;li&gt;Flushes (writes out) any data still in their buffers.&lt;/li&gt;
&lt;li&gt;Returns a result code (typically 0 for success, non-zero for failure).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt; _IO_unbuffer_all ();&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This function iterates over all open FILE* streams and sets their buffering mode to unbuffered (like calling    setbuf(stream, NULL) for each).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. _IO_FILE_plus:&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;Before moving forward to &lt;code&gt;_IO_flush_all&lt;/code&gt; we need to do some discussion on &lt;code&gt;_IO_FILE_plus&lt;/code&gt;.....
What is &lt;code&gt;_IO_FILE_plus&lt;/code&gt; ? ?&lt;/p&gt;
&lt;p&gt;In user-level C code, you typically see streams as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FILE *fp = fopen(&quot;data.txt&quot;, &quot;w&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But internally in glibc, a FILE is implemented as a struct defined in &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42/source/libio/bits/types/struct_FILE.h&quot;&gt;source/libio/bits/types/struct_FILE.h&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;struct _IO_FILE {
   int _flags;                // File status flags (read/write/eof/error)
   char *_IO_read_ptr;        // Current read pointer in the buffer
   char *_IO_read_end;        // End of readable buffer
   char *_IO_read_base;       // Start of readable buffer
   char *_IO_write_base;      // Start of write buffer
   char *_IO_write_ptr;       // Current write pointer
   char *_IO_write_end;       // End of write buffer
   char *_IO_buf_base;        // Base of allocated buffer (for read/write)
   char *_IO_buf_end;         // End of allocated buffer
   char *_IO_save_base;       // Backup of buffer base (used in ungetc)
   char *_IO_backup_base;     // Backup buffer base
   char *_IO_save_end;        // Backup buffer end
   struct _IO_marker *_markers;  // Linked list of markers (used for positioning)
   struct _IO_FILE *_chain;      // Next FILE in linked list of open streams
   int _fileno;               // File descriptor (OS handle)
   int _flags2 : 24;          // Extra flags for internal use
   char _short_backupbuf[1];  // Tiny backup buffer for special cases
   __off_t _old_offset;       // Previous file offset (for seek operations)
   unsigned short _cur_column;// Current column number (for text streams)
   signed char _vtable_offset;// Offset of vtable pointer in object (0 for normal FILE)
   char _shortbuf[1];         // Tiny buffer for putc/ungetc
   _IO_lock_t *_lock;         // Lock for thread-safe access
   __off64_t _offset;         // Current file position (64-bit offset)

   // Wide character support
   struct _IO_codecvt *_codecvt;  // Codecvt object for character conversion (wide char support)
   struct _IO_wide_data *_wide_data; // Buffer and state for wide-character I/O
   struct _IO_FILE *_freeres_list;    // List of freed FILE objects (for cleanup)
   void *_freeres_buf;                // Buffer used for freeing FILEs
   struct _IO_FILE **_prevchain;      // Previous FILE in the global chain
   int _mode;                          // Stream orientation: 0 = undecided, &amp;gt;0 = wide, &amp;lt;0 = byte
   char _unused2[20];                  // Padding / reserved for future use
};

//Finally
struct _IO_FILE_plus
{
 FILE file;
 const struct _IO_jump_t *vtable;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do not get afraid of these whole entries 😅  , for our exploit part we need to just focus more on these entries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt; _chain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_lock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_wide_data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_mode&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_IO_jump_t *vtable&lt;/code&gt;  [This one is most important..]&lt;/li&gt;
&lt;li&gt;Apart from the above entries we would need to understand some char * of &lt;code&gt;read&lt;/code&gt;,&lt;code&gt;write&lt;/code&gt;,&lt;code&gt;buf&lt;/code&gt;,&lt;code&gt;save&lt;/code&gt;,&lt;code&gt;backup&lt;/code&gt;..&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So when we call fopen to open our file it basically do some initialization of these file struct like&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fopen()  
 └── _IO_new_fopen()  
      └── _IO_new_file_fopen()  
           ├── _IO_file_open()     ← does low-level open() syscall
           ├── _IO_file_init()     ← initializes vtable &amp;amp; buffering
           └── returns _IO_FILE_plus object  // this is our struct file
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;&lt;code&gt;_chain:&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;Let&apos;s say you opened two files named &lt;code&gt;file1.txt&lt;/code&gt; and &lt;code&gt;file2.txt&lt;/code&gt; , then
On opening any of these file we receive a &lt;code&gt;_IO_FILE_plus&lt;/code&gt;  struct  containing &lt;code&gt;_fileno&lt;/code&gt; entries with the file descriptor returned by kernel i.e if i open &lt;code&gt;file1.txt&lt;/code&gt; first then &lt;code&gt;_fileno=3 &lt;/code&gt; and then open &lt;code&gt;file2.txt&lt;/code&gt; then its &lt;code&gt;_fileno=4&lt;/code&gt;.
Now , we will observe that &lt;code&gt;_chain&lt;/code&gt; entries of both file would be different...
Before moving to &lt;code&gt;_chain&lt;/code&gt; I would like to introduce you with a very famous pointer , I m calling him famous because It is a global pointer inside glibc’s libio layer named &lt;code&gt;_IO_list_all&lt;/code&gt;.&lt;/p&gt;
&lt;h6&gt;&lt;code&gt;_IO_list_all:&lt;/code&gt;&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;It points to the head of a linked list of all currently active (open) FILE* streams.&lt;/li&gt;
&lt;li&gt;It’s essential for process cleanup because it contain list of of all opened  file pointer&lt;/li&gt;
&lt;li&gt;Initially it contain  &lt;code&gt;_IO_list_all → _IO_2_1_stderr_ (fd=2)&lt;/code&gt; , as we open any other file it is added in the head of  &lt;code&gt;_IO_list_all&lt;/code&gt; like &lt;code&gt;_IO_list_all → OurFile_pointer(fd=3)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In last point as I told you each new file opened is connected to head of &lt;code&gt;_IO_list_all&lt;/code&gt; but what about previously connected file pointer and how &lt;code&gt;_IO_list_all&lt;/code&gt; is going to connect those all files ??
These doubts will now connect us with the use of &lt;code&gt;_chain&lt;/code&gt; entries  because this &lt;code&gt;_chain&lt;/code&gt; entries do nothing but contain the entries of pointer which was connected to the head of &lt;code&gt;_IO_list_all&lt;/code&gt; before currently opened file Or we can say that entries of &lt;code&gt;OurFile_pointer(fd=3)-&amp;gt;_chain&lt;/code&gt; will be pointer to &lt;code&gt;_IO_2_1_stderr_(fd=2)&lt;/code&gt; ,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_IO_2_1_stderr_(fd=2)-&amp;gt;_chain =  _IO_2_1_stdout_(fd=1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_IO_2_1_stdout_(fd=1)-&amp;gt;_chain =  _IO_2_1_stdin_(fd=0)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_IO_2_1_stdin_(fd=0)-&amp;gt;_chain =  NULL&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Observation: &lt;code&gt;FD(n)-&amp;gt;_chain = FD(n-1)&lt;/code&gt; each file pointer  &lt;code&gt;_chain&lt;/code&gt; contain previously opend file pointer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5&gt;&lt;code&gt;_lock:&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;To understand this entries , first think &lt;strong&gt;why do we need this one ?&lt;/strong&gt;
Since we are dealing with Files , which mean it has to do something with read and write also in this modern era we have very fast computers or CPU right ?
These speed are due to multiple cpu or multiple threads , this is the case where we need to understand the importance of file operations under the condition of multiple thread who want to read or write the same file without any race condition..
So to avoid these race condition , we need to implement mutual exclusion or mutex locking system to avoid wrong result by locking  our file resources to be used by only one thread at once and wait by others.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;These implementation to avoid race conditon is done by setting our &lt;code&gt;_lock&lt;/code&gt; with the mutex object&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_lock&lt;/code&gt; is either set to &lt;code&gt;NULL&lt;/code&gt; or writable&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;pwndbg&amp;gt; p *(pthread_mutex_t *)stdout-&amp;gt;_lock
$9 = {
  __data = {
    __lock = 0,
 ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Thsese are mutex  pointer in stdout&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;code&gt;_wide_data:&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;Whenever you write C , python code ,etc. you generally follow ASCII character , nothing new in it .. But while you are chatting with someone , it is not necessary that you always type in ASCII , sometime you need to show your emotion with some emoji , but &lt;strong&gt;have you ever wondered how much emoji your phone have and How ASCII can represent more than 255+ emojis ?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Again we can&apos;t represent those emojis with just &lt;code&gt;0xff&lt;/code&gt; or &lt;code&gt;1 byte&lt;/code&gt; limited ASCII  values we need something more to represent it .
There comes our &lt;code&gt;_wide_data&lt;/code&gt; to manage those extra sized character.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_wide_data&lt;/code&gt; is a pointer to a separate structure that stores buffers, pointers, and state for wide-character I/O.&lt;/li&gt;
&lt;li&gt;Regular char I/O (like fwrite) uses &lt;code&gt;_IO_write_base&lt;/code&gt; / &lt;code&gt;_IO_write_ptr&lt;/code&gt; / &lt;code&gt;_IO_buf_base&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Wide wchar_t I/O uses &lt;code&gt;_wide_data-&amp;gt;_IO_write_base&lt;/code&gt; / &lt;code&gt;_IO_write_ptr&lt;/code&gt; / &lt;code&gt;_IO_buf_base&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;code&gt;_mode:&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;By reading it someone might misinterpret it like mode of file for read, write, truncate, etc.. But
The &lt;code&gt;_mode&lt;/code&gt; field does not represent read/write mode — &lt;strong&gt;It represents the character orientation of the file stream (whether it handles &lt;code&gt;normal bytes&lt;/code&gt; or &lt;code&gt;wide characters&lt;/code&gt;)&lt;/strong&gt;
Now you can connect with the above &lt;code&gt;_wide_data&lt;/code&gt; , how our regular I/O uses is using &lt;code&gt;_IO_writ_base&lt;/code&gt; and wide mode uses &lt;code&gt;_wide_data-&amp;gt;_IO_write_base&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_mode&lt;/code&gt; indicates whether the stream is &lt;code&gt;byte-oriented&lt;/code&gt;, &lt;code&gt;wide-oriented&lt;/code&gt;, or not yet decided.&lt;/li&gt;
&lt;li&gt;It helps glibc determine whether to use normal I/O buffers (&lt;code&gt;_IO_write_ptr&lt;/code&gt;, &lt;code&gt;_IO_read_ptr&lt;/code&gt;) or wide-character buffers (&lt;code&gt;_wide_data-&amp;gt;_IO_write_ptr&lt;/code&gt;, &lt;code&gt;_wide_data-&amp;gt;_IO_read_ptr&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The _mode field is signed int:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;→ orientation not yet determined (stream unused or undecided)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;0&lt;/code&gt;→ byte-oriented stream (used by &lt;code&gt;printf&lt;/code&gt;, &lt;code&gt;fread&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;0&lt;/code&gt; → wide-character-oriented stream (used by &lt;code&gt;fwprintf&lt;/code&gt;, &lt;code&gt;fgetwc&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;code&gt;_IO_jump_t *vtable:&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;This is the most important field if you want to understand how &lt;code&gt;_IO_FILE_plus&lt;/code&gt; implements polymorphic behavior for all kinds of &lt;code&gt;I/O&lt;/code&gt; operations.
&lt;code&gt;vtable &lt;/code&gt; basically contain table of fuctions which would be called via &lt;code&gt;_IO_OVERFLOW(fp, EOF);&lt;/code&gt; according to which function is using this file struct i.e when you call &lt;code&gt;fwrite(fp):&lt;/code&gt;  it is redirected to
&lt;code&gt;fp-&amp;gt;vtable-&amp;gt;xsputn(fp, buf, n);&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vtable   &lt;/code&gt; is  like a menucard of function that our File is allowed to do.&lt;/li&gt;
&lt;li&gt;Without &lt;code&gt;vtable&lt;/code&gt;, glibc would need if/else checks for every stream type.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;struct _IO_jump_t {
    size_t __dummy;               // placeholder, not used
    size_t __dummy2;              // placeholder, not used
    _IO_finish_t __finish;        // called when finishing stream (cleanup buffers)
    _IO_overflow_t __overflow;    // called when writing to a full buffer
    _IO_underflow_t __underflow;  // called when reading from empty buffer
    _IO_underflow_t __uflow;      // called to read a single character
    _IO_pbackfail_t __pbackfail;  // called when ungetc fails (pushing back char)
    _IO_xsputn_t __xsputn;        // called to write n bytes (fwrite uses this)
    _IO_xsgetn_t __xsgetn;        // called to read n bytes (fread uses this)
    _IO_seekoff_t __seekoff;      // called to seek by offset (fseek)
    _IO_seekpos_t __seekpos;      // called to seek to a specific position
    _IO_setbuf_t __setbuf;        // called to set buffering mode (setvbuf)
    _IO_sync_t __sync;            // called to flush buffers (fflush)
    _IO_doallocate_t __doallocate;// called to allocate internal buffer if needed
    _IO_read_t __read;            // low-level read (OS read)
    _IO_write_t __write;          // low-level write (OS write)
    _IO_seek_t __seek;            // low-level seek (lseek wrapper)
    _IO_close_t __close;          // low-level close (fclose wrapper)
    _IO_stat_t __stat;            // get file status (fstat)
    _IO_showmanyc_t __showmanyc;  // estimate number of characters available to read
    _IO_imbue_t __imbue;          // set locale/encoding (for wide-char streams)
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3. Now move Inside _IO_flush_all()&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;After learning lots about File struct , we are now confident to understand the code below
What does &lt;code&gt;_IO_flush_all&lt;/code&gt; do :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lock &lt;code&gt;_IO_list_all&lt;/code&gt; --&amp;gt; for thread-safety (Multiple threads might be writing to different streams; we don’t want to flush while someone else is modifying one.)&lt;/li&gt;
&lt;li&gt;It walks the linked list &lt;code&gt;_IO_list_all&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For each stream:
&lt;ul&gt;
&lt;li&gt;Check if there’s buffered data ( uses &lt;code&gt;_mode&lt;/code&gt; to identify , if we need to flush &lt;code&gt;_wide char&lt;/code&gt; or &lt;code&gt;normal bytes&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;Flush via _IO_OVERFLOW(fp, EOF)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Handle errors (set result = EOF)&lt;/li&gt;
&lt;li&gt;Unlock global list&lt;/li&gt;
&lt;li&gt;Return success/failure&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a new entry where you may feel new i.e. &lt;code&gt;_IO_vtable_offset(fp) == 0&lt;/code&gt;  , This condition checks whether the FILE object &lt;code&gt;fp&lt;/code&gt; is a standard/normal FILE stream, meaning its vtable pointer is located at the expected position (offset 0) in memory. If not 0 then our file stream is custom like &lt;code&gt;FILE *fp = fmemopen(buf, sizeof(buf), &quot;w&quot;);&lt;/code&gt; , but we generally do not use these standard unless we requir more customize form..
So, As our current writup we would assume for standared file stream for &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;fopen&lt;/code&gt;, etc.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int
_IO_flush_all (void)
{
  int result = 0;
  FILE *fp;

#ifdef _IO_MTSAFE_IO
  _IO_cleanup_region_start_noarg (flush_cleanup);
  _IO_lock_lock (list_all_lock); //lock global list all
#endif

  for (fp = (FILE *) _IO_list_all; fp != NULL; fp = fp-&amp;gt;_chain) // started loop to scan all opened file pointer via the concurrent process
    {
      run_fp = fp;
      _IO_flockfile (fp); //lock the file to avoid race condition via another thread

      if (((fp-&amp;gt;_mode &amp;lt;= 0 &amp;amp;&amp;amp; fp-&amp;gt;_IO_write_ptr &amp;gt; fp-&amp;gt;_IO_write_base)  //  checking for normal byte or not decided and then checking if we are in mid of writing or not , if we are then need to flush it before end of main thread
     || (_IO_vtable_offset (fp) == 0 //checking for standared stream file pointer 
         &amp;amp;&amp;amp; fp-&amp;gt;_mode &amp;gt; 0 &amp;amp;&amp;amp; (fp-&amp;gt;_wide_data-&amp;gt;_IO_write_ptr
            &amp;gt; fp-&amp;gt;_wide_data-&amp;gt;_IO_write_base)) // again checking for any pending _wide_data (_mode&amp;gt;0) buffer
     )
    &amp;amp;&amp;amp; _IO_OVERFLOW (fp, EOF) == EOF) //do flush if any pending buffer ## This is our target now to explore..
  result = EOF; 

      _IO_funlockfile (fp); //unlock the file pointer to be used by another thread
      run_fp = NULL;
    }

#ifdef _IO_MTSAFE_IO
  _IO_lock_unlock (list_all_lock);
  _IO_cleanup_region_end (0);
#endif

  return result;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Code:&lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.40.9000/source/libio/genops.c#L712&quot;&gt;_IO_flush_all&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;4. _IO_OVERFLOW (fp, EOF)&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;In &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/libioP.h#L148&quot;&gt;libioP.h&lt;/a&gt; , It defined as macros &lt;code&gt;#define _IO_OVERFLOW(FP, CH) JUMP1 (__overflow, FP, CH)&lt;/code&gt;  and for &lt;code&gt;JUMP1&lt;/code&gt; defined as
&lt;code&gt;#define JUMP1(FUNC, THIS, X1) (_IO_JUMPS_FUNC(THIS)-&amp;gt;FUNC) (THIS, X1)&lt;/code&gt;
Now we need to understand &lt;code&gt;_IO_JUMPS_FUNC(THIS)&lt;/code&gt;&lt;br /&gt;
It is again defined as macros in  &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/libioP.h#L109&quot;&gt;libioP.h&lt;/a&gt; as :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# define _IO_JUMPS_FUNC(THIS) \
  (IO_validate_vtable                                                   \ 
   (*(struct _IO_jump_t **) ((void *) &amp;amp;_IO_JUMPS_FILE_plus (THIS) \
           + (THIS)-&amp;gt;_vtable_offset)))
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;THIS&lt;/code&gt; is a pointer to a FILE object (&lt;code&gt;FILE *fp&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_IO_JUMPS_FILE_plus(THIS)&lt;/code&gt; , This is another macro/function (glibc internal) that gives the base memory address where the vtables for files are stored&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+ (THIS)-&amp;gt;_vtable_offset&lt;/code&gt; , we already discussed it  ; shoud be  = &lt;code&gt;0&lt;/code&gt; ;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_IO_jump_t *vtable = *(struct _IO_jump_t **)vtable_addr;&lt;/code&gt;  assign &lt;code&gt;*vtable&lt;/code&gt; the base address of &lt;code&gt;fp-&amp;gt;vtable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vtable = IO_validate_vtable(vtable);&lt;/code&gt; // this is an important step to verify the correctness of &lt;code&gt;vtable&lt;/code&gt; pointer.&lt;/li&gt;
&lt;li&gt;Now &lt;code&gt;_IO_JUMPS_FUN(THIS)&lt;/code&gt; will be replaced by &lt;code&gt;vtable&lt;/code&gt; pointer  and &lt;code&gt;JUMP1(THIS,X1)&lt;/code&gt; will call &lt;code&gt;(vtable-&amp;gt;FUNC)(THIS,X1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FUNC&lt;/code&gt; is offset of &lt;code&gt;vtable&lt;/code&gt; functions based on verstion of libc. I&apos;m testing on libc. 2.4 where &lt;code&gt;FUN = 3&lt;/code&gt; for &lt;code&gt;__overflow&lt;/code&gt; or &lt;code&gt;call [vtable+0x18]&lt;/code&gt;  with 1 extra argument &lt;code&gt;x1&lt;/code&gt; according to &lt;code&gt;JUMP1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now In our journey we reached upto &lt;code&gt;_IO_file_overflow&lt;/code&gt; via &lt;code&gt;exit()-&amp;gt;__run_exit_handlers()-&amp;gt;_IO_cleanup()-&amp;gt;_IO_flush_all()-&amp;gt;_IO_file_overflow()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Moving to next journey.. 📈&lt;/p&gt;
&lt;h1&gt;Finally !!, Exploitation&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;Till now we reached upto &lt;code&gt;call [vtable+0x18]&lt;/code&gt; , if you observer in &lt;code&gt;vtable&lt;/code&gt; it is &lt;code&gt;__overflow&lt;/code&gt; at offset &lt;code&gt;0x18&lt;/code&gt;
This is the core function glibc uses for flushing/writing to a file when the buffer is full.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/fileops.c#L765&quot;&gt;_IO_new_file_overflow()&lt;/a&gt; offset:0x18&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;_IO_file_overflow() handles overflow in a FILE stream’s buffer.
&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;C&lt;/code&gt;, when we write to a &lt;code&gt;FILE *&lt;/code&gt; stream &lt;code&gt;(fputc, fwrite, fprintf, etc.)&lt;/code&gt;, the data usually goes to a buffer in memory first.&lt;/li&gt;
&lt;li&gt;The buffer is &lt;code&gt;flushed&lt;/code&gt; (written to the underlying file descriptor or &lt;code&gt;_filno&lt;/code&gt;) when it’s full or when you call &lt;code&gt;fflush()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But now our main focus is on, &lt;strong&gt;What if we are able to write this &lt;code&gt;vtable&lt;/code&gt; pointer ??&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have added challenge file which will allow us to take input directly to file pointer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this challenge we are able to take input uputo &lt;code&gt;0xff bytes&lt;/code&gt; , to overwrite file struct
Now , think what can we over-write  to vtable pinter ??
If we remember , while Jumping to &lt;code&gt;_IO_OVERFLOW(FP, CH)&lt;/code&gt; we have to pass throug a vtable check &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/libioP.h#L1033&quot;&gt;&lt;code&gt;IO_validate_vtable(vtable)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IO_validate_vtable (const struct _IO_jump_t *vtable)
{
  uintptr_t ptr = (uintptr_t) vtable;
  uintptr_t offset = ptr - (uintptr_t) &amp;amp;__io_vtables; // in above case we were at offset 0x18 to call __Overflow
  if (__glibc_unlikely (offset &amp;gt;= IO_VTABLES_LEN)) // IO_VTABLE_LEN = sizeof(struct _IO_jump_t)
    _IO_vtable_check (); //cause error if failed to check
  return vtable; 
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inside &lt;code&gt;_IO_validate_vtable&lt;/code&gt; it checks for our offset of &lt;code&gt;vtable&lt;/code&gt; functions , it cannot allow us to call those functions which are not inside  &lt;code&gt;_IO_jump_t&lt;/code&gt; struct i.e. our pointer &lt;code&gt;*vtable&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It looks like we stuck here ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So we need to pass a valid &lt;code&gt;vtable&lt;/code&gt; pointer which can call some vulnerable function whose calling function can be controlled by our forged file struct.
There is a separate type &lt;code&gt;vtable&lt;/code&gt; for wide char flush operation that uses our &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42/source/libio/libio.h#L121&quot;&gt;wide_data struct&lt;/a&gt;  (we already have a small discussion on this ) entry of our forged file pointer.
This special &lt;code&gt;vtable&lt;/code&gt; for wide char is &lt;code&gt;_IO_wfile_jump&lt;/code&gt; , its pointer lies in &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/libioP.h#L519&quot;&gt;&lt;code&gt;__io_vtable&lt;/code&gt;&lt;/a&gt; so we can use this to call the function related to wide char operations.&lt;/p&gt;
&lt;p&gt;After over-writing our vtable with &lt;code&gt;_IO_wfile_jump&lt;/code&gt;  our &lt;code&gt;call [vtable+0x18]&lt;/code&gt; will now call &lt;code&gt;_IO_wfile_overflow&lt;/code&gt; to manage wide char instead of &lt;code&gt;__overflow&lt;/code&gt; for normal bytes.&lt;/p&gt;
&lt;p&gt;Now look inside &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/wfileops.c#L407&quot;&gt;_IO_wfile_overflow&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wint_t
_IO_wfile_overflow (FILE *f, wint_t wch)
{
  if (f-&amp;gt;_flags &amp;amp; _IO_NO_WRITES) /* SET ERROR */
    {
      f-&amp;gt;_flags |= _IO_ERR_SEEN;
      __set_errno (EBADF);
      return WEOF;
    }
  /* If currently reading or no buffer allocated. */
  if ((f-&amp;gt;_flags &amp;amp; _IO_CURRENTLY_PUTTING) == 0
      || f-&amp;gt;_wide_data-&amp;gt;_IO_write_base == NULL)
    {
      /* Allocate a buffer if needed. */
      if (f-&amp;gt;_wide_data-&amp;gt;_IO_write_base == NULL) 
  {
    _IO_wdoallocbuf (f); // This is now our target function to call
    _IO_free_wbackup_area (f);

    if (f-&amp;gt;_IO_write_base == NULL)
      {
        _IO_doallocbuf (f);
        _IO_setg (f, f-&amp;gt;_IO_buf_base, f-&amp;gt;_IO_buf_base, f-&amp;gt;_IO_buf_base);
      }
    _IO_wsetg (f, f-&amp;gt;_wide_data-&amp;gt;_IO_buf_base,
         f-&amp;gt;_wide_data-&amp;gt;_IO_buf_base, f-&amp;gt;_wide_data-&amp;gt;_IO_buf_base);
  }
  ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;_IO_wdoallocbuf()&lt;/code&gt; ensure the &lt;code&gt;FILE&lt;/code&gt; stream f has an appropriate buffer for wide-character operations (wchar/wide I/O).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;_IO_doallocbuf (FILE *fp)
{
  if (fp-&amp;gt;_IO_buf_base) // checks if buff is already allocated
    return;
  if (!(fp-&amp;gt;_flags &amp;amp; _IO_UNBUFFERED) || fp-&amp;gt;_mode &amp;gt; 0) //This checks whether the stream is buffered. If the _IO_UNBUFFERED flag is not set, the stream is intended to use a buffer and therefore we should try to allocate one
    if (_IO_DOALLOCATE (fp) != EOF) // it is responsible for  actual work of allocating and installing a buffer for a FILE *
      return;
  _IO_setb (fp, fp-&amp;gt;_shortbuf, fp-&amp;gt;_shortbuf+1, 0);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will now focus on &lt;code&gt;_IO_DOALLOCATE&lt;/code&gt;  :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is implemented as macros &lt;code&gt;#define _IO_WDOALLOCATE(FP) WJUMP0 (__doallocate, FP)&lt;/code&gt;in &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.42.9000/source/libio/libioP.h#L225&quot;&gt;libioP.h&lt;/a&gt; same as we discussed &lt;code&gt;JUMP1&lt;/code&gt; above.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#define WJUMP0(FUNC, THIS) (_IO_WIDE_JUMPS_FUNC(THIS)-&amp;gt;FUNC) (THIS)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#define _IO_WIDE_JUMPS_FUNC(THIS) _IO_WIDE_JUMPS(THIS)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;#define _IO_WIDE_JUMPS(THIS) \
  _IO_CAST_FIELD_ACCESS ((THIS), struct _IO_FILE, _wide_data)-&amp;gt;_wide_vtable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the above points , we can conclude that how we are using &lt;code&gt;_wide_data-&amp;gt;_wide_vtable&lt;/code&gt; pointer same as &lt;code&gt;fp-&amp;gt;vtable&lt;/code&gt; to call the required function form the list of vtable.
But this time our &lt;code&gt;_wide_data&lt;/code&gt; struct will be pointing to the our forged File struct to controll the call function&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note : This time we will be able to call arbitrary functions due to no check for valid vtable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In disassembly of &lt;code&gt;_IO_wdoallocbuf&lt;/code&gt; we are calling as
&lt;img src=&quot;./do_alloc.png&quot; alt=&quot;_IO_wdoallocbuf&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rdi = _IO_2_1_stdout struct pointer
mov    rax, qword ptr [rdi + 0xa0]   // move rax = _IO_wide_data struct pointer
   ...
mov    rax, qword ptr [rax + 0xe0]   // move rax = _IO_wide_data-&amp;gt;_wide_vtable (In our case it is pointing to our File Struct)
call   qword ptr [rax + 0x68]        // calling  _IO_wide_data-&amp;gt;_wide_vtable + 0x68 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we will set our &lt;code&gt;_IO_wide_data-&amp;gt;vtable+0x68&lt;/code&gt; to our favourite  pointer &lt;code&gt;0xdeadc0de&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;STEPS OF EXPLOIT:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;fp-&amp;gt;_lock = libc.sym._IO_2_1_stdout_ +0x1000&lt;/code&gt; to some writable area&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fp-&amp;gt;_IO_write_ptr = 1&lt;/code&gt; to pass check &lt;code&gt;fp-&amp;gt;_IO_write_ptr &amp;gt; fp-&amp;gt;_IO_write_base&lt;/code&gt; in &lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.40.9000/source/libio/genops.c#L727&quot;&gt;_IO_flush_all&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Need to point to fake vtable which uses &lt;code&gt;_wide_data&lt;/code&gt; to vulnerable call . &lt;code&gt;fp-&amp;gt;vtable = libc.sym._IO_wfile_jumps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set our &lt;code&gt;_IO_wide_data&lt;/code&gt; = &lt;code&gt;_IO_2_1_stdout +0x8&lt;/code&gt; in our File struct to set fake &lt;code&gt;_IO_wide_data&lt;/code&gt; pointer looks like &lt;code&gt;_IO_FILE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Now &lt;code&gt;_IO_wide_data-&amp;gt;_wide_vtable+0x68&lt;/code&gt; will be at offset of &lt;code&gt;_chain&lt;/code&gt; of our &lt;code&gt;fp&lt;/code&gt; pointer , so set &lt;code&gt;fp-&amp;gt;_chain&lt;/code&gt; = &lt;code&gt;0xdeadc0de&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Again these offset depend upon the libc version. , you need to work on gdb to figure out how these offset are are calling which function and where.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Finally we controlled our program counter!!&lt;/strong&gt; &lt;img src=&quot;./0xdeadc0de.png&quot; alt=&quot;0xdeadc0de.png&quot; /&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Thanks for Reading!!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>