I'm trying to search the memory of a running Linux process for UTF-16 strings and return the address of each match. I've already parsed /proc/PID/maps and can identify the readable memory regions, but I'm unsure how to dump and scan those ranges reliably. I tried combining shell tools such as gdb, dd, and grep, but ran into various problems. The target text is known to be UTF-16 because I located one instance with a memory-inspection tool, and I'd also like to detect changes while the process is running. Is this practical in Bash, or would a small C/C++ program be the better approach?
3 Answers
Make sure the encoding assumption is correct. UTF-16 in memory could be little-endian or big-endian, and a program might store strings as UTF-8, UTF-32, wide-character objects, or a custom representation instead. Test both byte orders and account for whether the text has a terminating two-byte zero. Also remember that the address returned is only valid for that particular process run because address-space layout and allocations can change.
The shell utility strings is mainly intended for ordinary single-byte text and does not normally report virtual addresses. You can sometimes dump a mapped region and process it with shell tools, but Bash is awkward for binary data, UTF-16 matching, null bytes, endianness, and address calculations. A small C or C++ scanner will be much more reliable and faster: parse the mappings, read each permitted range, compare against the UTF-16 byte pattern, and add the match offset to the mapping’s start address.
It may be possible to assemble a shell pipeline, but that doesn’t make it a good fit. Tools such as dd and grep can lose information or interpret binary data unexpectedly, especially when UTF-16 includes zero bytes.
Linux exposes a process’s address space through /proc/PID/mem, while /proc/PID/maps tells you which virtual-address ranges exist and what permissions they have. For each readable region, open /proc/PID/mem, seek to the region’s starting address, read its bytes, and search for the UTF-16 representation. You’ll need appropriate permissions, commonly the same user plus ptrace access, or elevated privileges. Be careful with mappings that disappear or change while you read them.
A core dump can also be searched, but it represents a snapshot, so it won’t show strings that change afterward. If you need live updates, scan /proc/PID/mem repeatedly or instrument the process instead.

A core dump is useful for offline analysis, but getting a match address from it requires mapping the dump’s file offsets back to the process virtual addresses. Reading the live memory mapping directly is simpler when you need the actual current address.