This is a small app (by HAWKE, 2009) which requires us to find the correct serial key. The goal is to produce a keygen as opposed to patching. Patching is just easy as changing one instruction.
1. Load the Sandwich.app in Hopper Disassembler, choose the default and proceed to disassembly screen.
2. Instead of remote server, we will connect to the current system using Hopper Debugger Server. Download, install and run the app which will launch the debug server locally.

3. Now in the Hopper, navigate to
Debug->Select Debugger...
and the server will be listed under local servers section. Double click to launch the server window.4. The path will be auto filled to something like
/Users/.../Sandwich.app/Contents/MacOS/Sandwich
. Click the Play icon under controls which will run the Sandwich.app under the debugger.5. Check the left pane for the available methods. We can see
-[SandwichAppDelegate validateSerial:]
method. Check the pseudo code to get an idea of the algorithm.
6. Now is the time to add breakpoints so that we can step and check register values as the program runs. So add to the initial address
00001b2d 55 push ebp
under that section.7. Go back to the running program and enter some serial number and click validate, which will make the debugger stop at the breakpoint.
8. The first conditional check is
cmp eax, 0x13
which checks if the serial number is 19 decimals long.
9. Second check is
mov dword [esp+0x28+var_20], 0x2034 ; @"-"
which then checks the number of components separated by -
and compares it with cmp eax, 0x4
, which means, the serial key has four dashes in it. So the format is xxxx-xxxx-xxxx-xxxxx

10. If all the above passes, it gets each block (chunk separated by dash) and check if length is four.

11. Next it takes the first block
0x0
gets the int value and place it into esi
register mov esi, eax
.
12. Then it takes the second block
0x1
, get the int value and adds it to the block 1 esi
value from above step and place it into esi
register itself.
13. There is no check for third block which means it can be any random characters of length four.
14. The last block is constructed by computing shift arithmetic right by two of the current esi
sar esi, 0x2
from step 12 and then subtracting it from 0x19c5
the HEX for 6597
loaded into edx
and then comparing the obtained value to the last block from the serial key loaded into eax

15. If it match, the serial key is correct and a success dialog will be shown. Now that we know the algorithm, we can write the keygen.

The keygen code
#!/usr/bin/python
"""Sandwich OS X crackme keygen by qlisp.
App: https://reverse.put.as/wp-content/uploads/2010/05/1-Sandwich.zip
Tue 28 Nov 17
"""
import random
class SandwichKeygen:
"""Sandwich key generator."""
__block_3_mn = 6597 # block 3 magic number
def _gen_random(self):
"""Return random number in range of 4 digits."""
return random.randrange(1000, 9999)
def _get_block(self):
"""Get a block containing 4 digits."""
return str(self._gen_random())
def _get_block_3(self, block_1, block_2):
"""Generate the last block from block 1."""
sar_2 = (int(block_1) + int(block_2)) >> 2
return str(self.__block_3_mn - sar_2)
def generate(self):
"""Generates the key."""
block_0 = self._get_block()
block_1 = self._get_block()
return '-'.join([block_0, block_1, str(self._gen_random()), self._get_block_3(block_0, block_1)])
if __name__ == '__main__':
keygen = SandwichKeygen()
print keygen.generate()
# Few keys
1111-2222-0000-5764
2681-8944-2259-3691
6773-1497-8343-4530
5903-2519-1731-4492
9613-1094-3343-3921