Recovering the SIM card PIN from the ZTE WF721 cellular home phone

As seen on Hackaday!

TL;DR – If you have a ZTE WF721 that’s PIN-locked your SIM card, try 2376.

Recently I picked up a used Samsung Galaxy Core LTE smartphone from a relative after they upgraded to an iPhone. As the Core LTE is a low-end smartphone, I suspected that the phone was SIM locked to its original carrier (Virgin Mobile), but in order to test this I needed a different SIM card. My personal phone was on the same carrier, so I wasn’t able to use that to test it.

However, the previous summer I picked up a ZTE WF721 cellular home phone base station (that is, it’s a voice-only cell phone that a landline phone plugs into), which came with a Telus SIM card. The issue is that the WF721 sets a SIM card PIN to essentially “lock” the card to the base station, and it wasn’t the default 1234 PIN; brute-forcing a SIM card is not possible as you get 3-5 attempts before the card needs to be unblocked using a PUK (PIN Unblock Key), failing that, the card is permanently rendered unusable. I decided to take the base station apart, and use my knowledge in electronics and previous research into smart cards to see if I could recover the PIN.

(Yes, I went through all this work instead of just buying a prepaid SIM card from the dollar store. I’m weird like that.)

Test Pads & Signals

After a bit of disassembly work involving removing screws hidden under rubber non-slip feet and a lot of spudgering open plastic clips, I got access to the four test pads that connect to the SIM card, accessible on the opposite side of the PCB from the SIM card socket.

ZTE WF721 Opened

The ZTE WF721 opened, with test pads broken out and connected to DSLogic for reverse engineering.

An ISO 7816-compliant smart card (and a SIM card is one) require 5 different lines to work: Vcc (power), ground, clock, I/O (data), and reset. The I/O is an asynchronous half-duplex UART-type interface, whose baud rate is determined by the card’s characteristics and the clock frequency that it is given by the reader (in this case, the WF721). The details of how the interface work can be obtained for free in their TS 102 221 specification from the ETSI (European Telecommunications Standards Institute).

ZTE WF721 SIM Card Test Pads

The test pads that connect to the WF721’s SIM card socket.

I then soldered the ground wire to a free test pad elsewhere on the board, whereas the four other wires were soldered to the test pads near the SIM card socket. I then connected these wires to a pin header and plugged it into my DSLogic Plus logic analyzer. I analyzed the logic captures after turning the WF721 on and allowing it to initialize the SIM card and attempt to connect to the cellular network (the service to it has been disconnected so it doesn’t actually succeed).

Command Analysis

After looking at the raw logic capture, there was a lot that I had to sift through. I needed to create a custom setting for the UART decoder as the serial output isn’t your traditional “9600-8-N-1” setting. Rather, the interface uses 8 data bits, even parity, and 2 stop bits. The baud rate is determined by a parameter in the card’s initial identification, the ATR (Answer to Reset). I parsed the card’s ATR that I previously captured on the PC using the SpringCard PC/SC Diagnostic tool using Ludovic Rousseau’s online tool, I determined I needed to use a baud rate of 250 kbit/s, since the card was being fed a 4 MHz clock.

T=0 Smart Card Command (APDU) Structure

The smart card communicates to and from the host through APDUs (Application Protocol Data Units). The command header for a T=0 smart card (character-based I/O, which most cards use) is made up of 5 bytes: class, instruction, 2 parameter bytes and a length/3rd parameter byte. To acknowledge the command, the card sends the instruction byte back to the reader and the data is transferred to/from the card, depending on the command used. The card then sends two status bytes that indicate whether the command is successful; if it is, the response is 0x9000. A graphical representation of this process can be seen in the next section.

VERIFY PIN Command Decoding

The raw data structure of a SIM card's VERIFY PIN command. Each part of the flow is labeled for ease of understanding.

The raw data structure of a SIM card’s VERIFY PIN command. Each part of the flow is labeled for ease of understanding (click image to see full size).

The command I’m looking for is 0x20 (VERIFY PIN), and I had to sift through the command flow in the logic analyzer until I found it. After a lot of preceding commands, I found the command I was looking for, and I found the PIN… and it’s in plaintext! As it turns out, it is sent as an ASCII string, but it’s not null terminated like a regular string. Instead, the data is always 8 bytes (allowing up to an 8-digit PIN), but a PIN shorter than 8 digits will have the end bytes padded with 0xFF (all binary ones). It was easy to determine that the bytes 0x32 33 37 36 is the ASCII representation of the PIN 2376, and after the card waited many tens of milliseconds, it acknowledged the PIN was correct as it gave the expected 0x9000 response code.

PIN Testing & Unlocking

SIM Opened in Dekart SIM Manager

Dekart SIM Manager showing the phone number programmed into the SIM card (censored for privacy).

I tried the PIN in the Dekart SIM Manager software on my computer, and it worked! I was able to read out the contents of the SIM and find out what phone number it used to have, although no other useful information was found.

By using the legacy GSM class 0xA0, I was able to manually verify the PIN by directly communicating with the SIM card using the same command syntax in PC/SC Diagnostic:


Testing the VERIFY PIN command directly in SpringCard PC/SC Diagnostic.

I took the SIM card out and put it in my Galaxy Core LTE phone, entered the PIN, and as expected it brought up the network unlock prompt. I was able to contact my carrier to get the phone unlocked, and they did it for free (as legally required in Canada) – it turned out to be helpful I was on the same network, as they needed an account to authenticate the request against, even if the phone is registered to another account holder. After entering the 8-digit unlock PIN they provided, the phone was successfully unlocked!

The WF721 is in all likelihood also network locked, but that’s a bridge I haven’t crossed yet.


After a bit of sleuthing into how SIM cards communicate with a cell phone, I was able to decipher the exact command used to authenticate a SIM card PIN inside a disused cellular home phone, all to check if a hand-me-down smartphone was network-locked to its original carrier. Was it a lot of effort just to do that? Maybe, but where’s the fun in buying a prepaid SIM card? 🙂


18 thoughts on “Recovering the SIM card PIN from the ZTE WF721 cellular home phone

  1. Pingback: Recovering the SIM card PIN from the ZTE WF721 cellular home phone – Rip It Apart – Jason’s electronics blog-thingy – The Library 6.0

  2. TLDR: SIM PIN is 2376.
    Wow thank you so much! A true evil device to secretly add a PIN to every sim card you put it in. My grandfather received this device in a gift exchange and locked 2 of our SIM cards by trying it out. Thanks to you our SIM cards are now unlocked, I love the internet.

    Liked by 2 people

  3. Pingback: Ramble: 2019 in review | Rip It Apart – Jason's electronics blog-thingy

  4. Pingback: Jason Gin Reverse Engineers the SIM Lock PIN From ZTE WF721 Cellular Home Phone Base Stations - PC Solution

  5. Pingback: Ramble: 2020 in review | Rip It Apart – Jason's electronics blog-thingy

  6. hi.
    im on the same road here,,, 250kb/s 4 mhz card.. using sigrok pulseview and saele chinese knockoff analyzer. what sample rate do i have to use for analysing? been trying here entire day but no luck.


    • I’d say at least 8 or 16 MHz if you’re looking to capture the clock too. Optionally you could just max out the sample rate on your Saleae clone as long as your system supports it.


      • im getting so much frame errors, parity errors.tried all kind of combinations with party and stop bits but still dont really trust the data.

        according to smart cards data is always most significant byte first, and data starts with falling edge, correct?


          • cool, im following Your blog here and trying to mimic what You have done. Smart card ATR parsing french website suggested that my card is 4mhz and 250000kb/s that must be same that You had. so baudrate im usin is 250000, even parity, 2 stop bits., 8 data bits.

            i got my analyzer yesterday so it is my first project to use/learn how to use it.. tnx for help man.

            can you remeber all the parameters you used, so i can use the same setup .



            • I’m using DSView which is a different tool, but these are the parameters I used:
              250000 baud rate, 8 data bits, even parity, parity check ignored, 1.5 stop bits (DSView won’t let me use 2), least significant bit first, non-inverted (idle high).

              Note that the data bits in a byte are least-significant bit first, but the data bytes themselves as part of a command are most-significant byte first.

              What is your measured clock frequency? Is it actually 4 MHz for your equipment?


              • I dont know my Mhz, have no scope. dont know how to find out either,

                got that from french site – Fi=512, Di=32, 16 cycles/ETU (250000 bits/s at 4.00 MHz, 312500 bits/s for fMax=5 MHz) – thats for my sim

                I was running analyser on 8739-8-2-EVEN this morning and got SIM card giving me back its ATR number (baudrate 8739 came from another blog, 9600 is not coming back accurate.) after that is some blank space and everything after that only frame errors and nothing useful. so im guessing that the SIM is changing baudrate but i’ve tried all the common ones but still no luck… seeing how 9600 is not giving anything useful either im thinkin that i need custom baudrate.. unfortunatly im all out of ideas …

                how to calculate baudrate?


                • Find the narrowest pulse from a falling edge to rising edge. The bit rate should be 1/(negative-going pulse width).

                  If you want, capture the output at the highest sampling rate, and email me the Saleae logic capture so I could try to figure out the parameters.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.