Mona v3 Released: ⚡ Faster 🎯 Leaner ⚙️ Broader

This article has 461 views

Long overdue...

Woohoo! It (finally) happened!

I'm really proud to announce the release of mona v3!

Monav3 ascii glow

This release has been a long time in the making.
While it still builds on some of the solid foundations of earlier versions, substantial parts of the codebase have been completely reworked, refactored, and modernized.

The result is a cleaner and broader version of mona, with improved compatibility and a more consistent runtime across supported environments.

What’s new

The good news

This new version is not only faster and leaner, it also brings a broader and more flexible runtime:

  • Full support for Python 2 and Python 3. We do recommend running mona on Python3
  • Runs on WinDBG, WinDBGX, and Immunity Debugger
  • Works with both 32-bit and 64-bit processes
  • Uses a more recent pykd library and the pykd-ext bootstrapper

Additionally, mona v3:

  • Relies less on pykd's access to symbols to run. Mona now natively does most of the heavy lifting, in a lot of areas of the process (modules, heap, etc).
  • Allows us to specify addresses, registers, symbol names, dereferenced registers with offsets, module names etc any time you can specific an address as an argument
  • Has improved table-based output
  • Features significant performance improvements in certain time-consuming routines (such as mona rop)
  • Helps you manage symbols, clean up unwanted disk space consumption caused by failed symbol file downloads
  • Has an improved wildcard search routine (findwild)
  • Shows an eta for long-running actions and searches
  • Allows you to interrupt long-running searches without killing your debugging session.
  • Uses clickable links in some output, making use and navigation even easier

The vast majority of existing mona commands remain available, and - as suggested in the list above - many have been improved in terms of behavior, stability, compatibility and/or performance.

The overall goal remains unchanged: to deliver high-quality, actionable output out of the box, while still allowing detailed control over search scope and behavior.

In addition, mona v3 includes a number of new features and commands.
Some of those will be covered in more detail in follow-up posts.

So, that's the good news.

Less-than-ideal news

There is also some less encouraging news to share.

When I started developing the first version of mona.py back in 2011, the primary goal was simple: make the tool easy to use and capable of producing actionable results out of the box. It was designed to run on a default installation of Python 2 together with Immunity Debugger — no additional libraries required.

Later, when adding support for WinDBG, that principle had to be relaxed with the introduction of the pykd library.

Today, as part of the ongoing effort to bring more functionality into 64-bit debugging sessions, I ran into another limitation: WinDBG(X) does not natively support assembling 64-bit mnemonics.

Crazy, right? 🤷🏼‍♂️

Since pykd depends on WinDBG and doesn't have its own built-in assembler, this created a new challenge: how to provide reliable 64-bit assembly capabilities without building and maintaining a custom assembler myself?

An initial attempt involved building a cache of commonly used instructions. However, while working on improvements to the findwild wildcard search command, it quickly became clear that this approach would not scale in a practical or maintainable way.

For now, the solution is to rely on the keystone-engine library.
To get the most out of mona.py on 64-bit targets, you will need to install keystone-engine via pip.
When installed, windbglib will automatically import and use it.
If not, it will fall back to the limited instruction cache and whatever WinDBG provides.
Even on 32-bit targets, windbglib will prefer Keystone if it is present before falling back to WinDBG’s native assembler.

That said, it appears the Keystone project is no longer actively maintained. Still, that didn’t stop us from using pykd either.

If you are aware of viable alternatives — ideally a lightweight, actively maintained assembler library with solid 32-bit and 64-bit support and easy installation via pip on Python 3.9+ — feel free to reach out.

Acknowledgements

Before we dive into the practical side, I want to take a moment to give credit where it’s due.

A huge thank you to @apl3b for his dedication, persistence, and high-quality work.

He rewrote significant parts of the core routines, improved performance across multiple areas, and introduced several new features and commands.

This release would not be what it is without his contribution.

I would also like to thank angelo5d0 for his help testing the various features and commands in the updated mona/windbglib codebase.

Prerequisites

Before installing mona v3, it’s worth making sure your environment is clean and ready.

Cleaning up

If you have older versions of mona lying around, now is a good time to remove them.

  • Delete existing mona.py and windbglib.py copies from your debugger directories
  • Remove the pykd.pyd file from your WinDBG Program folder as well
  • Remove any Python installations that you're not using or plan on using

Starting clean helps avoid subtle issues later on.

Installing dependencies

Python 3.9 + PyKD + bootstrapper + libraries

The mona3 github repo contains the full setup instructions.

The main prerequisites are:

  • Python3.9.13 (32bit and 64bit) - that's the most recent Python3 version that ships the PyKD Python library version via pip
  • The corresponding PyKD Python library for both Python architectures
  • PyKD-ext WinDBG Extension, used as bootstrapper.
  • The keystone-engine Python library for both Python architectures

You can have other Python 3 versions installed on the system, but please note that mona won't run in a Python version that doesn't have the pykd library.

The CorelanTraining github repository contains a CorelanPyKDInstall.ps1 powershell script that will install all of the aforementioned components. I recommend using the script and carefully checking the output for errors.
The script has been tested on a handful of virtual machines, Windows 10 and Windows 11. Make sure your machines are up-to-date and everything should run smoothly.

Of course, you can also install all required components by hand.
In that case, I'd like to refer you to the corresponding procedure as documented in this blogpost on WinDBG Automation and Scripting. (Check out the section on PyKD.)

Note: That procedure does not cover how to install keystone-engine. That means you'll have to add the following 2 steps to the procedure:

py -3.9-32 -m pip install keystone-engine

and

py -3.9-64 -m pip install keystone-engine

Feeling adventurous?

A few days after publishing my blog post on WinDBG automation, I received a message on X from @gerhart_x.
He explaineded that he managed to compile pykd against Python 3.14. You can find the release here.
So in theory, it means you may be able to install Python 3.14 and load the corresponding pykd.dll

Installing mona.py

Putting mona.py and windbglib.py in the right place

With mona3, you still have the option to put both mona.py and windbglib.py inside your WinDBG program folder.

However, we're proposing a different approach now.

The mona3 GitHub repository has instructions on performing a centralized installation, which involves creating a local folder.

We're using C:\Tools\mona3 in the documentation, but you can obviously put it anywhere you'd like.

Both mona.py and windbglib.py should reside in the same folder.

Of course, you can also simply perform a git clone https://github.com/corelan/mona3.git into C:\Tools if you'd like. That will also create the mona3 folder and put all the files from the repository inside that folder. (which is a bit overkill really, we only need the 2 python files)
Whatever you do, just take note of the full path of mona.py and make sure windbglib.py sits in the same folder. We'll need the full path to run mona in WinDBG.

A centralized setup simplifies maintance. Whenever you decide to run !mona up, it will update the scripts for all debuggers using it.

In WinDBG and WinDBGX, the mona.py script is referenced via its full path. We'll have the ability to use WinDBG aliases to provide us with the ability to just run !mona (instead of having to type the full path every time). We'll talk about this in a moment.

In Immunity Debuger, a symbolic link can be used to make mona.py appear in the PyCommands folder. That way, we can invoke mona just like before, by running !mona.

From an admin command prompt:

C:\>mklink "c:\Program Files (x86)\Immunity Inc\Immunity Debugger\PyCommands\mona.py" C:\Tools\mona3\mona.py
symbolic link created for c:\Program Files (x86)\Immunity Inc\Immunity Debugger\PyCommands\mona.py <<===>> C:\Tools\mona3\mona.py

mona.ini

Mona uses a mona.ini file to store certain configurations.
If you already had a mona.ini file present on your system and discovered by mona3, it will be moved over into the folder that contains mona.py.
In other words, everything will be centralized in one place.

Running mona.py

Once installed, running mona should feel familiar.

In WinDBG / WinDBGX, load the pykd bootstrapper:

!load pykd

(unlike what we did with previous versions of mona, we're not loading pykd.pyd! We're loading pykd.dll instead.

Next, execute mona using Python 3.9:

!py -3.9 C:\Tools\mona3\mona.py

If multiple Python versions are installed, specifying 3.9 avoids ambiguity. The debugger will automatically use the correct architecture.

As indicated above, we can make our lives easier by creating the following alias:

as !mona !py -3.9 C:\Tools\mona3\mona.py

This now allows us to run

!mona

As explained in the documentation, you can have WinDBG execute the required commands to load pykd and set up the alias automatically.

From there, all your usual commands are available — only now faster, more consistent, and working across more environments.

mona commands

First and foremost, the Mona3 Github repository has a wiki which has up-to-date documentation for every available command and global search options.

Nevertheless, the table below provides a current (and possibly outdated) overview of the available mona.py commands at the moment of release.
As commands may be removed, changed or added, please check the actual list of commands on your system to see what options you have.
Just like before, when running !mona without arguments, you'll see the Global Options, followed by a table of available commands.
The commands are filtered by architecture and debugger type.

Run !mona without arguments to see the commands that are available on your debugger / architecture combination.

Command / Alias x86 x64 Info Description
? / eval Evaluate expression
allocmem / alloc WinDBG only Allocate memory
assemble / asm Assemble instructions. ⚠️ Needs keystone-engine on x64
bpseh / sehbp 🔲 x64: No SEH on stack Set breakpoint on SEH funcs (stack)
breakfunc / bf Breakpoint on function
breakpoint / bp Manage breakpoints
bytearray / ba Create bytearray
changeacl / ca WinDBG only Change memory protection
cleanlog / clean 🆕 Free up diskspace by cleaning old log files
compare / cmp Compare memory with contents of a file
config / conf Config settings
copy / cp Copy memory
dump / dmp Dump memory
dumplog / dl WinDBG only Dump log file
dumpobj / do WinDBG only Dump object
egghunter / egg Create egghunter
encode / enc Encode payload
filecompare / fc Compare files
fillchunk / fchunk Fill (overwrite) a heap chunk
find / f Find pattern (bytes, strings, pointers, etc)
findmsp / findmsf Find cyclic offset on stack and registers
findwild / fw Powerful wildcard search. ⚠️ Needs keystone-engine on x64
fwptr / fwp Find writeable ptr that gets called
geteat / eat List/Query EAT
getiat / iat List/Query IAT
getpc Produce GetPC code
gflags / gf Show active global flags
header Parse a file and transform it into python code that generates it
heap Heap analysis. (work in progress!)
help / h Show help
info Show info about a given address
infodump / if Dump process contents for comparison
jmp / j Find 'JMP' to register trampoline
jop Find JOP gadgets
jseh 🔲 x64: no SEH on stack Find SEH trampolines outside of modules (may not be executable!)
load / ld Load file and copy contents to a memory location
moduleinfo / modinfo 🆕 Module details
modules / mod List modules
offset / os Calc offset
pageacl / pacl Process layout and permissions (pages)
pattern_create / pc Create pattern
pattern_offset / po Find pattern offset
peb / peb Show address of PEB
proclayout / pl 🆕 Process layout (entities)
rop Find ROP gadgets
ropfunc Find interesting functions for ROP in module IATs
seh 🔲 x64: no SEH on stack Find trampolines for SEH overwrite
sehchain / exchain 🔲 x64: no SEH on stack Get SEH chain (stack)
skeleton Exploit skeleton
stackpivot Find stackpivots
stacks List stacks for all threads
string / str Read/Write a string from/to memory
stringpos / strpos 🆕 Find position of content at address in ascii/unicode string in memory
suggest Suggest exploit (create metasploit module) (needs stack corruption with cyclic pattern)
sym 🆕 WinDBG only List, fetch & clean symbols
teb / teb Show address of TEB
tobp / 2bp WinDBG only Convert to bp
unicodealign / ua Unicode align
update / up Update mona
write / w Write bytes to a memory location

As you can see, we have already made a decent number of commands compatible with x64. We'll keep working on offering even more logic for both 32bit and 64bit in the future.

Basic Usage

Comands are executed using

!mona <command> [arguments]

For example, if you'd like to run the "assemble" routine and you'd like to get the opcode for the "jmp eax" instruction, you can run

!mona asm -s "jmp eax"

It's a good idea to tell mona to write its output into specific folders instead of writing them inside the WinDBG Program Folder.
You can do so by setting a configuration variable workingfolder to a path.
We recommend adding a %p subfolder to that path, telling mona to organize the output into subfodlers that have the process' imagename.

0:000> !mona config -set workingfolder c:\logs\%p
Hold on...

[ -- START -- ] Mona command started on 2026-04-19 11:44:18 (v3.0, rev 3000) 64bit 
[ -- START -- ] Python: 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)])
[ -- START -- ] PyKD: 0.3.4.15 

[+] Command used: !py c:\Tools\mona3\mona.py config -set workingfolder c:\logs\%p

[+] Saving new value for parameter 'workingfolder'
    Config file: c:\Tools\mona3\mona.ini
    Old value of parameter workingfolder = c:\logs\%p
    New value:

[+] Saving config file, modified parameter workingfolder
    mona.ini saved under c:\Tools\mona3
    Parameter       New value  
    -------------   -----------
    workingfolder    c:\logs\%p

[ -- END -- ] This mona.py action took 0:00:00.069025
[ -- END -- ] Current date/time: 2026-04-19 11:44:18

Also, it would be great to adopt the habit of checking for updates on a regular basis. We're actively fixing bugs, adding features and making changes overall.

Just like before, checking for updates and updating itself in-place is as easy as running !mona up
(Make sure you have an active internet connection).

As explained before, if you're using a centralized setup, all of your debuggers will be using the updated version automatically.

Global options & default filters

The Global Options are a set of arguments and criteria that allow you to steer and control the searches that mona performs.
You'll get to see them when running !mona without arguments:

Global options :
----------------
You can use one or more of the following global options on any command that will perform
a search in one or more modules, returning a list of pointers :

  Global options affecting selection of modules:

  -n                     : Skip modules that start with a null byte. If this is too broad, use
                           option -cp nonull instead
  -o                     : Ignore OS modules
  -m <module,module,...> : only query the given modules. Be sure what you are doing !
                           You can specify multiple modules (comma separated)
                           Tip : you can use -m *  to include all modules.
                           All other module criteria will be ignored
                           Other wildcards : *blah.dll = ends with blah.dll, blah* = starts with blah,
                           blah or *blah* = contains blah
  -cm <crit,crit,...>    : Apply some additional criteria to the modules to query.
                           You can use one or more of the following criteria :
                           aslr,safeseh,rebase,nx,cfg,os
                           You can enable or disable a certain criterium by setting it to true or false
                           Example :  -cm aslr=true,safeseh=false
                           Suppose you want to search for p/p/r in aslr enabled modules, you could call
                           !mona seh -cm aslr
  -cmp <regex>           : Only include modules whose full path matches the given regex (case-insensitive)
                           Example : -cmp kernel32  -cmp "C:\\Windows"  -cmp "\.dll$"

  Global options affecting addresses:

  -p <nr>                : Stop search after  pointers.
  -cp <crit,crit,...>    : Apply some criteria to the pointers to return
                           Available options are :
                           unicode,ascii,asciiprint,upper,lower,uppernum,lowernum,
                           numeric,alphanum,nonull,startswithnull,unicoderev
                           Note : Multiple criteria will be evaluated using 'AND', 
                                  except if you are looking for unicode + one crit
  -cpb '\x00\x01'      : Provide list with bad chars, applies to pointers
                           You can use .. to indicate a range of bytes (in between 2 bad chars)
  -x <access>            : Specify desired access level of the returning pointers. If not specified,
                           only executable pointers will be returned.
                           Access levels can be one of the following values : R,W,X,RW,RX,WX,RWX or *


  Other global options:

  -h                     : Show help / usage for the selected command 
  -debug                 : Enable debug routines in mona/windbglib.
                           Don't use this option unless you've been asked to do so

There are 2 major types:

  • Options that affect the search scope, what areas of memory will be considered for the search
  • Options that affect the characteristics of the resulting addresses. Access controls, bad chars, things like that.

By default, almost all mona searches will exclude any module that has been REBASED or is ASLR enabled.

If you're looking for helpful pointers in relation with an exception handler overwrite, then it will exclude SAFESEH modules as well.

Within the remaining modules, mona will limit itself to pages that are marked as executable.
Technically, if your target does not have DEP enabled, then you may get away by selecting a pointer from a page that is not executable...

The exceptions to the non-rebase, non-aslr rule are:

  • findwild (will search in all executable pages)
  • getiat (will search in all modules)
  • geteat (will search in all modules)

You can overrule mona's default search scope behaviour at any time.
You can tell mona.py to search in specific modules regardless of their mitigations. (use options -m or -cmp)
Or you can overrule the non-aslr and/or non-rebase filter generically using something like: -cm aslr=True,rebase=True
You can also overrule the decision to limit itself to executable pages with the -x flag. For instance, search in all readable pages: -x R

In any case, all of this implies you understand what you're doing. The fact that mona.py was not able to find something by default is very likely caused by a relevant mitigation or access level, and is usually not a mistake.
be careful when you overrule the default scope and criteria.

But sometimes is does make sense to overrule.
In full ASLR applications, after obtaining an information leak, we'd have to tell mona to search in the module that we leaked.
As indicated, Mona's -m flag allows you to specify the module you want to search in, overruling its default filters.

The mona output will now show the active filters and default choices it has made, reminding you of the importance and effect of those choices.

For example:

0:000> !mona jmp -r esp
Hold on...

[ -- START -- ] Mona command started on 2026-04-16 14:59:37 (v3.0, rev 3000) 32bit 
[ -- START -- ] Python: 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:24:45) [MSC v.1929 32 bit (Intel)])
[ -- START -- ] PyKD: 0.3.4.15 

[+] Command used: !py C:\Tools\mona3\mona.py jmp -r esp

[+] Processing arguments and criteria
    - Pointer access level : X
[+] Generating module info table, hang on...
    - Processing modules
    - Done. Let's rock 'n roll.
[+] Criteria: ASLR = False | REBASE = False
[+] Querying 1 modules
    - Querying module blah
    - Search complete, processing results
[+] Preparing output file 'jmp.txt'
    - (Re)setting output file c:\logs\blah\jmp.txt

Likewise, the list of loaded modules now indicates some selection and ordering criteria. Let's say you're connected to MS Edg (64bit) and you'd like to see all modules that contain the word "edge" in the full path:

0:015> !mona mod -cmp edge
Hold on...

[ -- START -- ] Mona command started on 2026-04-16 15:27:11 (v3.0, rev 3000) 64bit 
[ -- START -- ] Python: 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)])
[ -- START -- ] PyKD: 0.3.4.15 

[+] Command used: !py C:\Tools\mona3\mona.py mod -cmp edge

[+] Processing arguments and criteria
    - Pointer access level : X
    - Filtering modules by path matching : edge
[+] Generating module info table, hang on...
    - Processing modules
    - Done. Let's rock 'n roll.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Total nr of modules loaded: 20 | Nr of modules displayed after filters: 4 | PEB order: InLoadOrder
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Module filter applied: cmp = edge
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Base               | Top                | Size               | Rebase | ASLR  | CFG   | NXCompat | OS Dll | Version, ImageName & Path, DLLCharacteristics
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 0x00007ff774ec0000 | 0x00007ff7753a3000 | 0x00000000004e3000 | True   | True  | True  |  True    | False  | 147.0.3912.60 [msedge.exe] (C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe) 0xc160
 0x00007ffdfe1e0000 | 0x00007ffdfe696000 | 0x00000000004b6000 | True   | True  | True  |  True    | False  | 147.0.3912.60 [msedge_elf.dll] (C:\Program Files (x86)\Microsoft\Edge\Application\147.0.3912.60\msedge_elf.dll) 0x4160
 0x00007ffdc1710000 | 0x00007ffdd4849000 | 0x0000000013139000 | True   | True  | True  |  True    | False  | 147.0.3912.60 [msedge.dll] (C:\Program Files (x86)\Microsoft\Edge\Application\147.0.3912.60\msedge.dll) 0x4160
 0x00007ffdfdd70000 | 0x00007ffdfe1df000 | 0x000000000046f000 | True   | True  | True  |  True    | False  | 0.0.0.0 [ffmpeg.dll] (C:\Program Files (x86)\Microsoft\Edge\Application\147.0.3912.60\ffmpeg.dll) 0x4160
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

[+] Preparing output file 'modules.txt'
    - (Re)setting output file c:\logs\msedge\modules.txt

[ -- END -- ] This mona.py action took 0:00:00.368993
[ -- END -- ] Current date/time: 2026-04-16 15:27:11

When specifying module criteria and filters, you'll see them appear in the header of the module table.

Getting help

Unsure what arguments are certain command takes? Simply run the command with the -h flag, or run !mona help command (where "command" is the name of the command you're interested in)

For example:

!mona asm -h

You've asked for help about the 'assemble' command.  Here is the requested information:

Basic command:
--------------
   !py mona assemble
   !py mona asm

Usage:
------
Convert instructions to opcode. Separate multiple instructions with #.

Mandatory argument : -s <instructions> : the sequence of instructions to assemble to opcode

Interrupting mona.py

You can interrupt (most) potentially long-running routines in mona.py by creating a file named stop in the same folder as mona.py

For example:

echo "stop" > c:\tools\mona3\stop

mona.py will check for the file on a recurring basis (but it may not be instant though) and will hard-terminate the script if the file was found.
You obviously won't get results, but at least you don't have to kill your debugging session in case you'd like to try something else.

Customizing clickable links

Some mona.py commands will show clickable links in WinDBG(X), facilitating easy navigation.
By default, mona.py assumes that you've created a WinDBG alias, allowing you to run !mona at the WinDBG Command prompt.
(In fact, mona.py will query the WinDBG aliases to find the one that you're using, but it will only work if you have only one alias defined that points to the mona.py script)

The clickable links will have that alias name hardcoded in their commands (either the actual alias name, or just !mona if no unique alias was found.

However, you can avoid doing the lookup and set your alias name as a mona configuration variable.
Suppose you have decided to name your WinDBG alias !mona3 instead of !mona and you don't want to rely on mona.py to extracting it from your WinDBG aliases, you can tell mona.py to use the !mona3 alias in its clickable links by setting the alias config variable:

!mona3 config -set alias #mona3

(In order to avoid alias substitution when using the config command, please a # instead of !. mona.py will replace it back to !)

From this point forward, the clickable links will use !mona3.

Perhaps you don't even want to use a WinDBG alias.
In that case, you can set the alias config value to the actual command you're using. Again, don't forget to replace the ! with a #.
Once set, mona will use whatever value you've set in it clickable links.

For example:

!py -3.9 c:\Tools\mona3\mona.py config -set alias "#py -3.9 c:\Tools\mona3\mona.py"

Note: if a mona.py config value alias is set, it will use that one instead of doing an active lookup in your aliases.

Questions on using mona.py?

Feel free to drop by our Discord server and ask questions in the #mona channel. We'll be more than happy to help

Found a bug?

Please open an issue on Github and provide the steps to reproduce the problem.
For more sophisticated issues, we may ask you to run the command again with the -debug flag and to provide us the output.
(On WinDBG(X), the -debug flag will write the output to a logfile automatically using WinDBGs .logopen command.

What’s next

This release is just the beginning.

We’ll explore some of the new features and improvements in more detail in future posts, and we continue to work on adding more to mona v3.

Of course, we also encourage and invite anyone to write code, to add more cool features to mona and submit PRs.
Please check the CONTRIBUTING.md file for more info.

Stay tuned.

Stay in the loop

If you want to be the first to hear about new releases, deep dives, and upcoming content:

👉 If you haven't done so already, subscribe to the blog - you'll receive an update in your mailbox as soon as I publish a new post.
👉 Follow on social media. If you see something you like, please share it with others.

More is coming.


I hope you found this useful 🙏🏻 🤗

© Corelan Consulting BV. All rights reserved. ​The contents of this page may not be reproduced, redistributed, or republished, in whole or in part, for commercial or non-commercial purposes without prior written permission from Corelan Consulting bv. See our Terms of Use & Privacy Policy (https://www.corelan.be/index.php/legal) for more details.



Discover more from Corelan | Exploit Development & Vulnerability Research

Subscribe to get the latest posts sent to your email.

About the author

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.