A mechanism for automating input events on iOS
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



CHAOTICMARCH is an iOS App UI automation engine for aiding security testing. It tries to solve the problem of coverage during blackbox testing. It is often the case that a researcher is introduced to a new application and their first action is to "look" around to see what features the App has as well as what web API it uses. Triggering the web API through the UI has the advantage of giving a sample of parameters to fuzz later.

Doing manual clicking around of the App is time consuming and boring. Also doing it manually will probably miss things. However, automated test using CHAOTICMARCH means that the tests can be repeatable and thorough. Also, the researcher can spend their time observing the traffic rather than looking at UI.


The CHAORICMARCH engine supports building block functionality by providing functions to the LUA scripts to execute their logic.


  • log(String out) Output a string to syslog.
  • touchDown(int touchId, number x, number y) Simulate a touch on the screen. Use touchId, [0, 9] to distinguish between touch points.
  • touchUp(int touchId, number x, number y) A touch release.
  • touchMove(int touchId, number x, number y) After a touch down, you can signal that the point has moved, simulating a swipe.
  • usleep(number mircoseconds) A sleep is useful between touchUp/Down events to simulate human interaction.
  • inputTest(String text) Enter the text to whatever component is holding the keyboard focus.
  • adaptResolution(int width, int height) If desired, you can change the virtual resolution. This will affect all coordinate based events.
  • getResolution() return two numbers, width and height, representing current resolution.
  • adaptOrientation(int ORIENTATION_TYPE) Change the devices orientation.
  • hasComponentAt(String compname, int boxes_x, int boxes_y, int box_x, int box_y) Checks if a particular component i.e. UIButton is at a specific location. The location is defined by number of equally spaced sections along the X and Y, then specifying which box you want this component to be in. The coordinates are defined so to give the user the freedom to be imprecise.
  • hasTextAt(String text, int boxes_x, int boxes_y, int box_x, int box_y) Same as component but the engine will look for text at a specified box.
  • findOfTypes(String type1, ..., String "") Possibly the most useful function, it will return a dictionary of the locations of particular types of components.
  • getBundleID() Gives the string of bundle name. Useful for deciding how to proceed with execution.
  • showCircle(int id, number x, number y, number radius) Mostly used with touchEvent to show where the touch has occurred on the screen.
  • hideCircle(int id) Removed the circle of a particular ID, you get [0, 9] range of ID's.


You will need a JailBroken iOS device (an iPhone 5s) with Cydia and MobileSubstrate. Compile the dynamic library and upload it to the phone like this:

make && 
scp -P 3222 ./libchaoticmarch.dylib \
            root@ && 
scp -r -P 3222 ./lua root@

The output will be in the syslog file: /var/log/syslog


By default, CHAOTICMARCH will not execute within any App. It needs to be configured. This is done in chaotic_march.lua file. There are selected CONFIGURABLE points. First is the maps that determines if the engine will run:

-- CONFIGURABLE: Enter bundles where to run
allowedBundles = {}
allowedBundles["com.highaltitudehacks.dvia"] = 1
allowedBundles["com.gs.pwm.external"] = 1
allowedBundles["com.apple.iBooks"] = 1

To ensure it runs within the desired App, add its identifier to the map. If you're not sure about the identifier, then run the App once and CHAOTICMARCH will log something like this (with the bundle ID):

Mar 18 17:06:37 iPhone CommCenterMobileHelper[2112]: CHAOTICMARCH: lua: Not running in: com.apple.commcentermobilehelper

You can also configure the initialization script. By default it is set to this:

-- CONFIGURABLE: execute user files
base_path = "/var/root/lua/"

First, the code will execute alphabetically sorted pre_all*.lua scripts. Then, it will execute bundle specific scripts [bundle_id]*.lua. Finally, it will execute post scripts post_all*.lua. This should give enough control to the developer to load libraries, set up environment and specify common functions before executing any App specific scripts.