데이터를 다루는 데 가장 기본이 되는 개념
컴퓨터는 0과 1만으로 수많은 데이터를 모두 표현, 처리
0과1을 나타내는, 컴퓨터에서 사용하는 테이터의 최소단위가 바로 1bit(binary digit의 약자인건 처음알았네!)
8비트 = 1바이트
메모리에 저장되는 최소 단위
Most Significant Bit (최상위 비트)
Least Significant Bit (최하위 비트)
'중요하다(Significant)' 는 표현을 붙이는 이유는 가장 왼쪽비트가 이진데이터(숫자)의 크기에 가장 큰 영향을 미치고 가장 오른쪽에 있는 비트는 반대로 가장 작은 영향을 미치기 때문이라고 한다.
크기가 2바이트 이상인 데이터는 메모리에 연속적으로 저장됨
각 바이트가 메모리에 정렬되는 방식 = 바이트 오더링
어떤 바이트 부터 낮은 주소에 저장되는지에 따라 2가지 방식으로 구분, 이해를 돕기 위해 '왼쪽에 있는 바이트일수록 '크다'고 표현'
빅 엔디안 방식 (Big Endian) : 큰 바이트부터 낮은 주소에 저장
리틀 엔디안 방식 (Little Endian) : 작은 바이트부터 낮은 주소에 저장
예시
0x01234567과 같은 데이터가 있을 때
여러 자료에서 MSB, LSB를 이용하여 바이트 오더링을 설명하는데 이때의 S는 'Significant
Bit' 가 아닌 'Significant Byte' 를 의미함
정교함과 정확함이 필수인 해킹 분야에서 데이터가 어떤 바이트 오더링으로 메모리에 저장되었는지를 고려하는것은 기본 중의 기본임
문자열은 바이트 오더링을 고려하지 않고 문자 순서 그대로 메모리에 저장
문자열이 아닌 데이터는 리틀 엔디안 방식으로 저장 -> 메모리의 높은 주소부터 읽어와서 출력
<기본형> x >> n : 원래 알고있는 비트를 n만큼 오른쪽으로 이동하는 시프트
x = x / 2^n
오른쪽으로 밀고 생긴 왼쪽 빈 칸은 기존의 MSB와 동일한 비트 값으로 채움 -> 부호가 유지
<기본형> x >>> n : 비트를 n만큼 오른쪽으로 이동한다는 행동은 같음
왼쪽 빈 칸을 MSB와 관계없이 모두 '0'으로 채움 -> 음수는 부호 유지가 안됨
어떤 데이터가 존재할 때, 특정 위치의 비트만 표시하거나 가리는 연산을 비트 마스킹(Bit Masking)이라고 부름. 피연산자 중 하나라도 '0'이면 연산결과값이 '0'인 AND의 특징을 활용하여 이해 레츠꼬
데이터의 비트를 표시하기 : 16진수F(1111) 는 특정 값과 AND 연산하면 기존 값에서 비트 값이 1이면 결과가 1, 0이면 결과가 0이기 때문에 기존 값과 동일한 결과가 나옵니다.
데이터의 비트를 숨기기 : 반대로 0(0000) 은 특정 값과 AND 연산하면 모든 비트가 0이 되어 결과는 0입니다.
32비트 즉, 4바이트 크기의 데이터인 0x12345678 에서 특정 비트만 가져오는 예시
(0001 0010 0011 0100 0101 0110 0111 1000)
- 상위비트들을 비트 마스킹으로 숨겨버리기 (0x000000FF와 AND 연산)
= 0x12345678 & 0x000000FF = 0x00000078
- 최상위비트를 최하위로 옮기기->3바이트만큼 밀어야하므로 3*8=24
- 1. 24번 오른쪽으로 논리 시프트(무조건'0')
= 0x12345678 >>> 24 = 0x00000012
- 2. 24번 오른쪽으로 산술 시프트(부호 고려) + 0x000000FF와 AND연산(MSB로 채운 앞부분을 비트 마스킹)
= 0x12345678 >> 24 & 0x000000FF
- 16번 우측으로 시프트 후 0x000000FF와 AND 연산
= 0x12345678 >> 16 & 0x000000FF = 0x00000034
- 4번 우측으로 시프트한 후 0x0000000F와 AND 연산
= 0x12345678 >> 4 & 0x0000000F = 0x00000007
기본적으로 원하는 특정바이트를 최하위 비트로 옮기기위해 시프트연산 + 상위비트에 데이터가 남아있으면 0x00....F..과 AND연산을 통해 비트 마스킹을 하는 구조
비교
비트 값이 같으면 '0'을 반환하는 XOR의 특징 이용
자기 자신과 XOR연산을 하면 결과는 항상'0'
두 변수에 저장된 데이터를 XOR 연산하여 결과가 '0'이면 두 값이 같다는 비교를 할 수 있음
암호화
어떤 값(x)에 어떤 값(y)을 2번 XOR하면 x와 동일해짐
예를 들어 x ^ y를 수행한 결과가 z일 때, z ^ y = x ^ y ^ y = x
따라서 y를 key로 설정하면 간단한 암복호화 가능
풀어서 설명하면 자기 자신과의 연산이 항상 '0'이다 라는 사실을 반대로 생각하면 자신과 00..00 사이의 연산결과는 항상 자신 (0은 0, 1은 1의 결과값을 갖기 때문)
암호화 : 데이터의 기밀성을 목적으로 타인이 데이터를 알아보지 못하게 변환하기 때문에 비밀키가 있어야만 원문 복구 가능
인코딩 : 누구나 표준화된 방식을 사용해서 디코딩하면 원문을 구할 수 있음
인코딩은 컴퓨터가 데이터를 효율적으로 다루도록 중요한 역할을 수행합니다. 어떤 인코딩된 데이터의 생김새를 보고 인코딩 방식을 유추하여 직접 디코딩해서 원문으로부터 단서를 얻어야 하는 경우도 있습니다. 이를 위해 자주 쓰이는 인코딩 방식과 각각의 형태를 알고 있으면 좋습니다.
우리가 입력하는 모든 글자가 0과 1로 변환되려면 숫자로 표현되어야 함. 이를 위한 것이 아스키 코드
미국에서 만들어서 알파벳 대소문자, 숫자, 특수 문자, 제어 문자만을 포함
아스키 문자 1개는 1바이트(8비트) = 7비트(문자 표현) + 1비트(오류 체크)
2^7 = 128가지의 문자표현 가능, 각 문자는 0~127의 10진수 값을 가짐
전세계 모든 언어의 문자에 숫자를 부여하는 국제 표준 코드가 바로 유니코드
4바이트(32비트)로 확장된 용량으로 문자 1개를 표현
유니코드의 처음 128개 문자는 아스키코드와 정확히 일치
LG도 아니고 접두어 U+로 표기 (U+16진수)
UTF-8, UTF-16, UTF-32 등 유니코드를 사용하는 다양한 인코딩 형식이 존재
가장 일반적으로 사용되는 UTF-8은 1~4 바이트의 가변적인 크기로 문자 1개를 표현하는 방식으로, 아스키 코드와 유사
웹에서 사용되는 URL은 특정 문자열만 허용. (알파벳 대소문자, 숫자, 그리고 일부 특수 문자)
허용되지 않는 문자, 즉 인코딩이 필요한 특수문자는 :/?#[]@!$&'()*+,;=%공백
URL인코딩은 % 기호 뒤에 이노딩이 필요한 해당 문자의 아스키코드 16진수 값을 붙여서 나타냄
ex) 공백(ASCII = 0x20)을 인코딩하면 -> %20