Skip to content
This repository has been archived by the owner on Sep 22, 2022. It is now read-only.

Commit

Permalink
Merge pull request #3 from qurbat/gpay
Browse files Browse the repository at this point in the history
  • Loading branch information
qurbat authored May 4, 2022
2 parents 69cd186 + 7bc0e38 commit 8d84d96
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config/config.ini
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ Please [refer to the documentation](https://razorpay.com/docs/payments/dashboard

## Usage
### Query all possible UPI addresses for the provided phone number
`upi-recon.py <phone_number>`
`upi-recon.py -p <phone_number>`
### Query all possible UPI addresses for the provided phone number using a specified number of threads
`upi-recon.py <phone_number> -t 5`
`upi-recon.py -p <phone_number> -t 5`
### Query a single UPI address for the provided phone number using a provided suffix
`upi-recon.py <phone_number> -s <suffix>`
`upi-recon.py -p <phone_number> -s <suffix>`
### Query all possible UPI addresses for the provided Gmail address
`upi-recon.py -g <gmail_username>`


## Contributions
Contributions are welcome. Feature wishlist:
- [x] Introduce support for Google Pay addresses
- [ ] Introduce support for more API providers
- [ ] Introduce support for wordlist based address discovery
- [ ] Improve argument parsing code
Expand Down
2 changes: 0 additions & 2 deletions config/config.ini

This file was deleted.

2 changes: 2 additions & 0 deletions config/config.ini.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[main]
api_key_id = your_key_goes_here
68 changes: 57 additions & 11 deletions upi-recon.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# -*- coding: utf-8 -*-

import argparse
import os
import requests
import concurrent.futures
import signal

from time import sleep
from random import uniform as rand
Expand All @@ -24,13 +24,15 @@
# Author: Karan Saini (@squeal)
# URL: https://github.com/qurbat/upi-recon
# Usage: upi-recon.py <phone_number> [query all possible UPI addresses]
upi-recon.py <phone_number> -t 5 [query all possible UPI addresses with specified number of threads]
upi-recon.py <phone_number> -s <suffix> [query a single UPI address with a specific suffix]
# Usage: upi-recon.py <phone_number> (query all possible UPI addresses)
upi-recon.py <phone_number> -t 5 (query all possible UPI addresses with specified number of threads)
upi-recon.py <phone_number> -s <suffix> (query a single UPI address with a specific suffix)
upi-recon.py -g <gmail_address> (query common Google Pay UPI addresses for specified google account)
"""

upi_suffix_dict = ['airtel', 'airtelpaymentsbank', 'apl', 'abfspay', 'allbank', 'andb', 'aubank', 'axis', 'albk', 'allahabadbank', 'apb', 'axisb', 'axisbank', 'axisgo', 'barodampay', 'barodapay', 'bandhan', 'birla', 'boi', 'cbin', 'cboi', 'centralbank', 'cnrb', 'dlb', 'eazypay', 'ezeepay', 'fbl', 'federal', 'freecharge', 'cmsidfc', 'csbcash', 'csbpay', 'cub', 'dbs', 'dcb', 'denabank', 'equitas', 'finobank', 'hdfcbank', 'hdfcbankjd', 'hsbc', 'ibl', 'icici', 'idbi', 'idbibank', 'idfcbank', 'icicibank', 'idfc', 'idfcnetc', 'ikwik', 'imobile', 'indianbank', 'indus', 'jkb', 'karurvysyabank', 'kaypay', 'kbl', 'kmb', 'kmbl', 'kotak', 'kvb', 'kvbank', 'lime', 'mahb', 'myicici', 'obc', 'okaxis', 'okhdfcbank', 'okicici', 'oksbi', 'paytm', 'payzapp', 'pingpay', 'pnb', 'pockets', 'rajgovhdfcbank', 'rbl', 'rmhdfcbank', 'sbi', 'sib', 'ubi', 'uboi', 'uco', 'unionbank', 'unionbankofindia', 'united', 'upi', 'utbi', 'ybl', 'yesbank', 'yesbankltd', 'indbank', 'indianbk', 'iob', 'jsbp', 'karb', 'lvb', 'lvbank', 'psb', 'purz', 'sc', 'scb', 'scbl', 'scmobile', 'srcb', 'synd', 'syndbank', 'syndicate', 'tjsb', 'vijayabank', 'vijb', 'vjb']

gpay_suffix_dict = ['okicici', 'oksbi', 'okaxis', 'okhdfcbank']

def address_discovery(vpa, api_url):
try:
Expand All @@ -51,7 +53,6 @@ def address_discovery(vpa, api_url):
# argument definition
parser = argparse.ArgumentParser(description='fetch UPI addresses and associated information for a given phone number')
# primary arguments
parser.add_argument('phone', type=str, help='phone number to query UPI addresses for')
parser.add_argument('-t', '--threads', type=int, default=None, help='number of threads to use for parallel address discovery')
parser.add_argument('-q', '--quiet', default=False, action='store_true', help='suppress banner')
# group arguments
Expand All @@ -60,9 +61,15 @@ def address_discovery(vpa, api_url):
group_2 = parser.add_mutually_exclusive_group()
group_2.add_argument('-a', '--all', default=True, action='store_true', help='query all suffixes')
group_2.add_argument('-s', '--suffix', type=str, help='query a specific suffix')
group_3 = parser.add_mutually_exclusive_group()
group_3.add_argument('phone', type=str, nargs='?', help='phone number to query UPI addresses for')
group_3.add_argument('-g', '--gpay', type=str, nargs='?', help='enter gmail address to query Google Pay UPI addresses for')
# parse arguments
arguments = parser.parse_args()
# check the configuration
if not os.path.exists('config/config.ini'):
print('[!] config/config.ini not found! please create the config file\n[!] you may refer to config/config.ini.example for help')
exit(1)
config = ConfigParser()
config_file = 'config/config.ini'
config.read(config_file)
Expand All @@ -76,33 +83,70 @@ def address_discovery(vpa, api_url):
# set variables and normalize input
API_URL = 'https://api.razorpay.com/v1/payments/validate/account?key_id='
api_key_id = config.get('main', 'api_key_id')
phone = arguments.phone[2:] if arguments.phone[0:2] == '91' and len(arguments.phone) > 10 else arguments.phone
if not arguments.gpay and not arguments.phone:
print('[!] please enter a phone number or gmail address')
exit(1)
if arguments.gpay and not arguments.phone:
email = arguments.gpay[:-10] if arguments.gpay.endswith('@gmail.com') else arguments.gpay
phone = '8888888888'
elif arguments.phone and arguments.gpay:
print('[!] please enter either a phone number or a gmail address')
exit(1)
elif arguments.phone:
phone = arguments.phone[2:] if arguments.phone[0:2] == '91' and len(arguments.phone) > 10 else arguments.phone
if len(phone) != 10:
print('[!] please enter a valid 10 digit phone number')
exit(1)
# check if api_key_id is correct
if api_key_id and not api_key_id[0:3] == 'rzp':
quit('[!] invalid api_key_id')
if not phone.isdigit():
quit('[!] phone number must be numeric')
quit('[!] phone number must be numeric. use -g to query Google Pay addresses')
# informational header
print('[i] starting at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))

# do the thing
if arguments.suffix: # query one
if arguments.suffix and arguments.gpay:
print('[!] cannot use suffix and gpay at the same time. please specify only one.')
exit(1)

elif arguments.suffix:
arguments.all = False
suffix = arguments.suffix[1:] if arguments.suffix[0] == '@' else arguments.suffix
print('[i] querying UPI addresses for phone number ' + phone)
address_discovery(phone + '@' + suffix, API_URL + api_key_id)
print('[i] finished at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
exit(1)

elif arguments.gpay:
if arguments.threads:
print('[i] querying Google Pay UPI addresses for ' + email + '@gmail.com with ' + str(arguments.threads) + ' threads')
with concurrent.futures.ThreadPoolExecutor(max_workers=arguments.threads) as executor:
for suffix in gpay_suffix_dict:
try:
executor.submit(address_discovery, email + '@' + suffix, API_URL + api_key_id)
sleep(rand(0.1, 0.2))
except KeyboardInterrupt as e:
print('\n[!] interrupted! stopping threads...')
exit(1)
print ('[i] finished at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
exit(1)
else:
print('[i] querying Google Pay UPI addresses for ' + email + '@gmail.com')
for suffix in track(gpay_suffix_dict):
address_discovery(email + '@' + suffix, API_URL + api_key_id)
print('[i] finished at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
exit(1)

elif arguments.all and not arguments.threads: # query all with no concurrency
print('[i] querying UPI addresses for phone number ' + phone)
for suffix in track(upi_suffix_dict):
address_discovery(phone + '@' + suffix, API_URL + api_key_id)
print('[i] finished at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
exit(1)

elif arguments.threads: # query all with threading
print('[i] querying UPI addresses for phone number ' + phone)
elif arguments.threads and not arguments.gpay: # query all with threading
print('[i] querying UPI addresses for phone number ' + phone + ' with ' + str(arguments.threads) + ' threads')
with concurrent.futures.ThreadPoolExecutor(max_workers=arguments.threads) as executor:
for suffix in upi_suffix_dict:
try:
Expand All @@ -111,5 +155,7 @@ def address_discovery(vpa, api_url):
except KeyboardInterrupt:
print('\n[!] interrupted! stopping threads...')
exit(1)
print('[i] finished at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
finally:
print('[i] finished at ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
exit(1)
exit(1)

0 comments on commit 8d84d96

Please sign in to comment.