OOO logo

OOO archive --- DEF CON CTF [ login ]

dc2019q - know_your_mem intro hinted good_first_challenge

by hacopo

This was a jeopardy challenge, part of dc2019q. (CTFtime)

Points: 109
Was solved by: 122 teams

You may spawn the server:

On your laptop
  • Install docker
  • docker pull archiveooo/pub:know_your_mem (docker-saved download)
  • docker run -d --name knowyourmem archiveooo/pub:know_your_mem
  • Local IP: docker inspect knowyourmem -f '{{ .NetworkSettings.Networks.bridge.IPAddress }}'
  • Connect to that IP:4669 — Remember to docker rm -f when done.
On your laptop (full source)
  • Install docker and pip install PyYAML coloredlogs
  • git clone (notice below)
  • cd know_your_mem
  • ./spawner --log-level=INFO
  • Connect to the ip:port displayed
Hosted by OOO Right now we're asking players to login first.


Find the flag page in memory, 64-bit edition. Timeouts are strict, please test locally first! There's a simplified version to help with that.

This was an introductory, easy challenge.

FYI, the v1 version allows for an easier solution that the one that is suggested. If you wish, v2 is slightly harder.

line_weight know_your_mem.c line_weight simplified.c line_weight line_weight shellcode.c line_weight Makefile line_weight line_weight


Hint 1Start by looking at syscalls. Only a few are allowed by the seccomp filter.
Hint 2Many syscalls can be used "indirectly" to check if memory is allocated at a certain address or not, without using signals or /proc/self/maps. How?
Hint 3Build a simple memory scanner using a syscall. Start on 32-bit. Can you make it faster? Can you distinguish read-write or read-only?
Hint 4Experiment with mmap() -- how does it behave with regards to memory that is already allocated? Try it on the local code.
Hint 5Use mmap() to first scan large chunks of memory. Try a chunk size of 64 KB. Look at the randomization function: not all memory addresses are possible.
Hint 6Once you drill down to find allocated single pages, how can you determine if the flag is there or not? See the source code.

If you wish, you can contribute more.

Further (spoilery) pointers

WhyExploring what is in memory is often an important part of remote code exploitation. One might think that restricting syscalls or eliminating /proc is enough to prevent it. Infoleak-by-failure is also a tricky aspect of API design.
A past caseVery few syscalls were available during DARPA's Cyber Grand Challenge, and segfaults were fatal. One of our (Shellphish) defenses instrumented jumps to make sure they were not reaching unallocated memory -- using this very technique.
Automatically creating shellcodeThe code we show here is obviously not the complete solution to writing shellcode in C. However, there are tools that help generate exploits semi-automatically. Look for ROP chain builders, for instance.
An easier leakHint: where could the address still be? What step we missed the last time we compiled it? (In my defense that was very close to game-start :)


Spoilers ahead! Code for this challenge is publicly available. There are two branches: v1 (as released) and v2 (with a fix)