Skip to content

Instantly share code, notes, and snippets.

@ttycelery
Last active November 1, 2023 02:45
Show Gist options
  • Save ttycelery/841c4239b8a94094f253e9d83ff4ad3f to your computer and use it in GitHub Desktop.
Save ttycelery/841c4239b8a94094f253e9d83ff4ad3f to your computer and use it in GitHub Desktop.
Read E-KTP image using PN532
"""
Author: Faiz J <askmehere@lcat.dev>
Date: 2023-11-01
Another proof of concept of a CompactByte blog article
https://blog.compactbyte.com/2018/06/10/membedah-e-ktp/
To run this script successfully, you must connect a PN532 reader to the USB
port of your computer using a USB-to-TTL converter (I use CH340). Enjoy!
"""
import struct
import sys
import nfc
if len(sys.argv) != 2:
print(f'usage: {sys.argv[0]} <output.jpg>')
sys.exit(1)
output_file = sys.argv[1]
clf = nfc.ContactlessFrontend('tty::pn532')
print('waiting for target')
tag = clf.connect(rdwr={'on-connect': lambda tag: False})
print('target detected, sending payloads')
print('selecting DF 7F0A')
resp = tag.transceive(bytearray.fromhex('00 A4 00 00 02 7F 0A'))
assert resp == b'\x90\x00'
print('selecting EF 6FF2')
resp = tag.transceive(bytearray.fromhex('00 A4 00 00 02 6F F2'))
assert resp == b'\x90\x00'
print('getting image size')
resp = tag.transceive(bytearray.fromhex('00 B0 00 00 02'))
size, status = struct.unpack('>HH', resp)
assert status == 0x9000
print(f'image size is {size} bytes')
print('reading image')
img_buf = bytearray()
chunk_size = 0x50
for offset in range(2, size, chunk_size):
command = bytearray.fromhex('00 B0')
command += struct.pack('>H', offset)
command += struct.pack('>B', chunk_size)
resp = tag.transceive(command)
chunk, status = struct.unpack(f'>{chunk_size}sH', resp)
assert status == 0x9000
img_buf += chunk
print(f'\rdone reading from offset {offset}', end='')
print(f'\nwriting to {output_file}')
with open(output_file, 'wb') as f:
f.write(img_buf[:size])
print(f'done!')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment