1. 문제
요즘 건물들에는 굴뚝이 없어서 산타가 몰래 들어가서 선물을 줄 수가 없다… 그래서 열쇠를 몰래 딸 수 있는 당신을 고용했다. 그런데 이 도어락은 우리가 흔히 보던 것과 좀 다른 것 같은데…? 원리만 이해하면 쉽게 딸 수 있을 것 같다!
Plain Text
복사
arm 어셈 덤프가 주어진다 - 다운로드
대회 당일 arm 어셈에 대한 지식이 부족해서 분석하다가 끝내 마무리하지 못했다. 롸업이 올라오고 나서 보니 그냥 분석해서 플래그 값을 얻어내면 되는 문제이다
2. 접근방법
main()
0000000000000c50 <main>:
c50: a9be7bfd stp x29, x30, [sp, #-32]! //스택공간 확보, sp=sp-32, push x29, push x30
c54: 910003fd mov x29, sp //sp 를 x29에 복사
c58: d2800021 mov x1, #0x1 // #1 초기 x1=1
c5c: d2800260 mov x0, #0x13 // #19 x0=0x13
c60: 97fffee0 bl 7e0 <calloc@plt> //0x13만큼 동적할당하고 1로 초기화
c64: f9000be0 str x0, [sp, #16] //sp+16에 calloc한 주소 저장
c68: 97ffff94 bl ab8 <sub_ab8>
c6c: 97ffff51 bl 9b0 <sub_9b0>
c70: f9000fe0 str x0, [sp, #24]
c74: 97ffff3e bl 96c <sub_96c>
c78: f9400be1 ldr x1, [sp, #16]
c7c: 90000000 adrp x0, 0 <_init-0x760>
c80: 9138a000 add x0, x0, #0xe28 // #0xe28 '%s'
c84: 97fffeeb bl 830 <__isoc99_scanf@plt>
c88: f9400fe1 ldr x1, [sp, #24]
c8c: f9400be0 ldr x0, [sp, #16]
c90: 97ffffa8 bl b30 <sub_b30>
c94: f9400be0 ldr x0, [sp, #16]
c98: 97fffee2 bl 820 <free@plt>
c9c: 52800000 mov w0, #0x0 // #0
ca0: a8c27bfd ldp x29, x30, [sp], #32
ca4: d65f03c0 ret
C
복사
•
몰랐던 instruction 위주로 설명하겠다. 우선 32바이트 만큼 스택을 확보하고, calloc(0x13,1)을 호출한다.
•
arm에서는 함수의 반환값을 x0 레지스터에 저장하므로 calloc을 통해 할당받은 힙주소를 sp+16에 저장한다. (buf)
•
sub_ab8() 함수를 호출한다. 반환되는 값은 x0에 담기므로 sub_9b0()은 x0를 인자로 하여 호출된다
•
함수 호출의 인자는 x0, x1, x2 ... 순인므로 scanf("%s", buf) 사용자의 입력을 받은 뒤 buf에 저장한다
•
buf(sp+16)와, sub_9b0() 반환값(sp+24)를 인자로 하여 sub_b30()이 호출된다
메인함수를 수도코드로 포팅하면 다음과 같이 표현할 수 있다
int main()
{
char* buf=calloc(0x13,1); //buf=sp+16
a=sub_9b0(sub_ab8()); // a= sp+24
b=sub_96c();
scanf("%s",buf);
sub_b30(buf,a);
return 0;
}
C
복사
sub_ab8()
0000000000000ab8 <sub_ab8>:
ab8: a9be7bfd stp x29, x30, [sp, #-32]! // sp-32만큼 확보하고 sp=sp-32, push x29, x30
abc: 910003fd mov x29, sp // sp를 x29에 복사
ac0: 52800103 mov w3, #0x8 // #8
ac4: 90000000 adrp x0, value0@page // 명령 포인터 복사
ac8: 9136e002 add x2, x0, value0@pageoff // x2=포인터+value0 즉, value2의 주소=>x2
acc: 528007c1 mov w1, #0x3e // #62
ad0: 90000000 adrp x0, value1@page // x0=value1 주소
ad4: 91372000 add x0, x0, value1@pageoff //x0=x0+value1주소
ad8: 97ffffc9 bl 9fc <sub_9fc>
adc: f9000fe0 str x0, [sp, #24]
ae0: f9400fe0 ldr x0, [sp, #24]
ae4: a8c27bfd ldp x29, x30, [sp], #32
ae8: d65f03c0 ret
C
복사
•
sub_9fc()에 들어가는 인자 4개를 세팅한다(x0, w1, x2, w3)
◦
(w- 계열 레지스터는 4byte 레지스터에고 8바이트 확장된게 x- 계열이다)
◦
w3 = 0x8
◦
x2 = value0
◦
w1 = 0x3e
◦
x0 = value1
•
sub_9fc(value1,0x3e,value0,w3)
•
위 함수의 반환값을 ret한다
sub_ab8()함수를 포팅하면 다음과 같다
sub_ab8()
{
return sub_9fc(value1,0x3e,value0,0x8); // a=sp+24
}
C
복사
sub_9fc()
00000000000009fc <sub_9fc>:
9fc: a9bc7bfd stp x29, x30, [sp, #-64]!
a00: 910003fd mov x29, sp
a04: f90017e0 str x0, [sp, #40] // x0=value1 주소
a08: b90027e1 str w1, [sp, #36] // w1=0x3e
a0c: f9000fe2 str x2, [sp, #24] // x2=value0 주소
a10: b90023e3 str w3, [sp, #32] // w3=8
a14: b94027e0 ldr w0, [sp, #36] // w0=0x3e
a18: 11000400 add w0, w0, #0x1 // w0=0x3f
a1c: 93407c00 sxtw x0, w0
a20: 97ffff68 bl 7c0 <malloc@plt> // 0x3f 사이즈 동적할당
a24: f9001fe0 str x0, [sp, #56] // 할당받은 주소를 sp+56에 저장
a28: b98027e0 ldrsw x0, [sp, #36] // x0에 0x3e 저장
a2c: f9401fe1 ldr x1, [sp, #56] // 할당 받은 주소를 x1에 저장
a30: 8b000020 add x0, x1, x0 // x0 = 할당받은 주소 + 0x3e
a34: 3900001f strb wzr, [x0] // wzr는 zero register. 항상 0이 들어감
a38: b90037ff str wzr, [sp, #52]
a3c: 14000018 b a9c <sub_9fc+0xa0> // ...a9c
---------------------------------------loop----------------------------------
a40: b98037e0 ldrsw x0, [sp, #52] // 초기값 0
a44: f94017e1 ldr x1, [sp, #40] //value1
a48: 8b000020 add x0, x1, x0 // value1 주소 + x0
a4c: 39400002 ldrb w2, [x0] // value1+x0에 담긴 한바이트를 w2에 저장
a50: b94037e0 ldr w0, [sp, #52] // 다시 초기값 0
a54: b94023e1 ldr w1, [sp, #32] // 8
a58: 1ac10c03 sdiv w3, w0, w1 // index / 8
a5c: b94023e1 ldr w1, [sp, #32]
a60: 1b017c61 mul w1, w3, w1 // (index/8)*8
a64: 4b010000 sub w0, w0, w1 // index - 8*(index/8)
a68: 93407c00 sxtw x0, w0
a6c: f9400fe1 ldr x1, [sp, #24] //x1=value0
a70: 8b000020 add x0, x1, x0 // x0 = value0 + x0
a74: 39400001 ldrb w1, [x0] // value0 한바이트 가져오기
a78: b98037e0 ldrsw x0, [sp, #52] // index
a7c: f9401fe3 ldr x3, [sp, #56] // buf
a80: 8b000060 add x0, x3, x0 // buf + index
a84: 4a010041 eor w1, w2, w1 // w1 =w2 ^ w1
a88: 12001c21 and w1, w1, #0xff // w1 = w1 & 0xff
a8c: 39000001 strb w1, [x0]
a90: b94037e0 ldr w0, [sp, #52]
a94: 11000400 add w0, w0, #0x1 // index++
a98: b90037e0 str w0, [sp, #52]
a9c: b94037e1 ldr w1, [sp, #52] // 초기값 0
aa0: b94027e0 ldr w0, [sp, #36] // 0x3e
aa4: 6b00003f cmp w1, w0
aa8: 54fffccb b.lt a40 <sub_9fc+0x44> // b.tstop
------------------------------------------------------------------------------
aac: f9401fe0 ldr x0, [sp, #56]
ab0: a8c47bfd ldp x29, x30, [sp], #64
ab4: d65f03c0 ret
C
복사
•
넘어온 인자 4개를 변수에 저장한다
•
0x3e+1 만큼 malloc한다
•
str wzr, [sp, #52] ⇒ wzr은 항상 0이 저장되고 0이 읽히는 레지스터이다. 따라서 sp+52에 0을 집어넣는다
•
sub_9fc+0xa0 로 이동한다 ⇒ 0x..a9c
•
sp+52 값인 0을 w1에 넣고, sp+36인 0x3e를 w0에 넣은뒤 두 개를 서로 배교한다. w1이 더 작으면 sub_9fc+0x44 ⇒ 0x..a40으로 다시 이동한다
•
sp+52를 인덱스로하여 특정 연산지 진행된다
a50: b94037e0 ldr w0, [sp, #52] // 다시 초기값 0
a54: b94023e1 ldr w1, [sp, #32] // 8
a58: 1ac10c03 sdiv w3, w0, w1 // index / 8
a5c: b94023e1 ldr w1, [sp, #32]
a60: 1b017c61 mul w1, w3, w1 // (index/8)*8
a64: 4b010000 sub w0, w0, w1 // index = index - 8*(index/8)
a68: 93407c00 sxtw x0, w0
C
복사
1.
value1 + index 의 한바이트 값을 가져온다. 초기 index(w0)는 0이다
2.
sp+32는 8이므로 w1에 저장한다
3.
(sp+52) - ((sp+52)/8) * 8 연산을 진행한다
4.
이 연산의 의미는 index = index - 8*(index/8) 이고 해당 index가 다음 루프의 index로 사용된다. 즉 value1[index %8] 로 해석하면 된다
5.
계산된 w0를 singed 부호확장을 진행하여 x0에 저장한다.
•
sp+52를 인덱스로 하여 이번에는 value0의 한바이트를 가져온다.
◦
value[index]
•
위에서 구한 두개의 값을 xor 연산하고 0xff와 and 연산을 진행한다
◦
( value1[index%8] ^ value0[index] ) & 0xff
•
계산된 한바이트를 malloc buf에 저장한다
•
루프가 끝나면 buf의 주소를 반환한다
해당 함수는 다음과 같이 표현 가능하다
sub_9fc(char* value1, int len, char* value0, int b)
{
char* arg1=value1;
int arg2=a; //0x3e
char* arg3=value0;
int arg4=b; //8
char* buf=malloc(arg2+1); // buf = sp+56
buf+0x3e=0;
for(i=0;i<len;i++)
{
buf[i]=( value0[i] ^ value1[i%b] ) & 0xff;
}
return buf;
}
C
복사
sub_9b0()
00000000000009b0 <sub_9b0>:
9b0: a9bd7bfd stp x29, x30, [sp, #-48]!
9b4: 910003fd mov x29, sp
9b8: f9000fe0 str x0, [sp, #24] // sub_9fc의 반환 값 저장
9bc: f9400fe0 ldr x0, [sp, #24]
9c0: 97ffff78 bl 7a0 <strlen@plt>
9c4: 91000400 add x0, x0, #0x1
9c8: 97ffff7e bl 7c0 <malloc@plt>
9cc: f90017e0 str x0, [sp, #40]
9d0: f94017e0 ldr x0, [sp, #40]
9d4: f100001f cmp x0, #0x0
9d8: 54000061 b.ne 9e4 <sub_9b0+0x34> // b.any
9dc: d2800000 mov x0, #0x0 // #0
9e0: 14000005 b 9f4 <sub_9b0+0x44>
9e4: f9400fe1 ldr x1, [sp, #24]
9e8: f94017e0 ldr x0, [sp, #40]
9ec: 97ffff95 bl 840 <strcpy@plt>
9f0: f94017e0 ldr x0, [sp, #40]
9f4: a8c37bfd ldp x29, x30, [sp], #48
9f8: d65f03c0 ret
C
복사
•
인자로 넘어온 연산된 값이 저장된 buf를 인자로 strlen이 호출된다. buf의 사이즈를 계산한다
•
strlen을 통해 얻은 사이즈 + 1만큼 malloc을 한다
•
할당받은 주소가 0이면 0x..9f4로 분기해서 종료되고 아니면 0x..9e4로 분기한다
•
sp+24인 buf의 주소와 할당받은 주소인 sp+40을 인자로 strcpy를 호출한다
•
즉 새롭게 할당받은 영역에 연산된 buf 를 복사하고 buf를 반환한다
위 함수는 다음과 같이 표현 할 수 있다
sub_9b0(int data)
{
b=strlen(data);
char* buf=malloc(b+1); //buf = sp+40
if(buf)
{
strcpy(buf,data);
return buf;
}
else
{
return 0;
}
}
C
복사
sub_b30(buf,a)
0000000000000b30 <sub_b30>:
b30: a9be7bfd stp x29, x30, [sp, #-32]!
b34: 910003fd mov x29, sp
b38: f9000fe0 str x0, [sp, #24] // x0값을 sp+24에 저장
b3c: f9000be1 str x1, [sp, #16] // x1값을 sp+16에 저장
b40: f9400fe0 ldr x0, [sp, #24] // sp+24를 읽어서 x0에 저장
b44: 91001800 add x0, x0, #0x6 // x0 = x0 + 6
b48: 39400001 ldrb w1, [x0] //x0에 들어있는 한바이트를 w1에 저장
b4c: f9400be0 ldr x0, [sp, #16] // sp+16을 읽어서 xo에 저장
b50: 91003800 add x0, x0, #0xe // x0 = x0+ 0xe
b54: 39400000 ldrb w0, [x0] // x0에 들어있는 한바이트를 w0에 저장
b58: 6b00003f cmp w1, w0
b5c: 54000761 b.ne c48 <sub_b30+0x118> // b.any
b60: f9400fe0 ldr x0, [sp, #24]
b64: 91001000 add x0, x0, #0x4
b68: 39400001 ldrb w1, [x0]
b6c: f9400be0 ldr x0, [sp, #16]
b70: 91000c00 add x0, x0, #0x3
b74: 39400000 ldrb w0, [x0]
b78: 6b00003f cmp w1, w0
b7c: 54000661 b.ne c48 <sub_b30+0x118> // b.any
b80: f9400fe0 ldr x0, [sp, #24]
b84: 91000c00 add x0, x0, #0x3
b88: 39400001 ldrb w1, [x0]
b8c: f9400be0 ldr x0, [sp, #16]
b90: 91002800 add x0, x0, #0xa
b94: 39400000 ldrb w0, [x0]
b98: 6b00003f cmp w1, w0
b9c: 54000561 b.ne c48 <sub_b30+0x118> // b.any
ba0: f9400fe0 ldr x0, [sp, #24]
ba4: 91001c00 add x0, x0, #0x7
ba8: 39400001 ldrb w1, [x0]
bac: f9400be0 ldr x0, [sp, #16]
bb0: 91004400 add x0, x0, #0x11
bb4: 39400000 ldrb w0, [x0]
bb8: 6b00003f cmp w1, w0
bbc: 54000461 b.ne c48 <sub_b30+0x118> // b.any
bc0: f9400fe0 ldr x0, [sp, #24]
bc4: 91000400 add x0, x0, #0x1
bc8: 39400001 ldrb w1, [x0]
bcc: f9400be0 ldr x0, [sp, #16]
bd0: 91003800 add x0, x0, #0xe
bd4: 39400000 ldrb w0, [x0]
bd8: 6b00003f cmp w1, w0
bdc: 54000361 b.ne c48 <sub_b30+0x118> // b.any
be0: f9400fe0 ldr x0, [sp, #24]
be4: 91001400 add x0, x0, #0x5
be8: 39400001 ldrb w1, [x0]
bec: f9400be0 ldr x0, [sp, #16]
bf0: 9100d000 add x0, x0, #0x34
bf4: 39400000 ldrb w0, [x0]
bf8: 6b00003f cmp w1, w0
bfc: 54000261 b.ne c48 <sub_b30+0x118> // b.any
c00: f9400fe0 ldr x0, [sp, #24]
c04: 39400001 ldrb w1, [x0]
c08: f9400be0 ldr x0, [sp, #16]
c0c: 9100d400 add x0, x0, #0x35
c10: 39400000 ldrb w0, [x0]
c14: 6b00003f cmp w1, w0
c18: 54000181 b.ne c48 <sub_b30+0x118> // b.any
c1c: f9400fe0 ldr x0, [sp, #24]
c20: 91000800 add x0, x0, #0x2
c24: 39400001 ldrb w1, [x0]
c28: f9400be0 ldr x0, [sp, #16]
c2c: 91000800 add x0, x0, #0x2
c30: 39400000 ldrb w0, [x0]
c34: 6b00003f cmp w1, w0
c38: 54000081 b.ne c48 <sub_b30+0x118> // b.any
c3c: f9400fe0 ldr x0, [sp, #24]
c40: 97ffffab bl aec <sub_aec>
c44: d503201f nop
c48: a8c27bfd ldp x29, x30, [sp], #32
c4c: d65f03c0 ret
C
복사
•
사용자가 입력한 값과 특정 연산이 수행된 값을 비교한다.
•
사용자의 입력값 8바이트를 각각 비교한다. 이를 다음과 같이 표현 할 수 있다
a=a+6;
b=b+0xe;
w1=*a;
x0=*b;
a=a+4;
b=b+3;
w1=*a;
x0=*b;
a=a+3;
b=b+0xa;
w1=*a;
x0=*b;
a=a+7;
b=b+0x11;
w1=*a;
x0=*b;
a=a+1;
b=b+0xe;
w1=*a;
x0=*b;
a=a+5;
b=b+0x34;
w1=*a;
x0=*b;
a=a+0;
b=b+0x35;
w1=*a;
x0=*b;
a=a+2;
b=b+0x2;
w1=*a;
x0=*b;
C
복사
•
8개의 조건을 다 만족한다면 이를 인자로 하여 sub_aec 함수를 호출한다
sub_aec(a)
0000000000000aec <sub_aec>:
aec: a9bd7bfd stp x29, x30, [sp, #-48]!
af0: 910003fd mov x29, sp
af4: f9000fe0 str x0, [sp, #24] // buf
af8: f9400fe0 ldr x0, [sp, #24]
afc: 97ffff29 bl 7a0 <strlen@plt>
b00: 2a0003e3 mov w3, w0
b04: f9400fe2 ldr x2, [sp, #24]
b08: 528003e1 mov w1, #0x1f // #31
b0c: 90000000 adrp x0, value2@page
b10: 91382000 add x0, x0, value2@pageoff
b14: 97ffffba bl 9fc <sub_9fc>
b18: f90017e0 str x0, [sp, #40]
b1c: f94017e0 ldr x0, [sp, #40]
b20: 97ffff3c bl 810 <puts@plt>
b24: d503201f nop
b28: a8c37bfd ldp x29, x30, [sp], #48
b2c: d65f03c0 ret
C
복사
•
사용자 입력값의 사이즈를 strlen을 통하여 얻는다
•
아까 봤던 sub_9fc()를 호출한다. 들어가는 인자는 다음과 같다
1.
x0 : value2 주소
2.
w1 : 0x1f
3.
w2 : 사용자 입력값 주소
4.
w3 : strlen을 통해서 얻은 사용자 입력 값 사이즈
3. 풀이
코드 분석은 다했다. 중요한 부분은 결국 다음과 같다
1.
value0, value1을 통해서 계산되는 buf의 값을 구한다
value1 = [
0xF7, 0x7B, 0x64, 0x75, 0xFC, 0x7F, 0x65, 0x79, 0xFF,
0x73, 0x6C, 0x7D, 0xF4, 0x77, 0x6D, 0x61, 0xE7, 0x6B, 0x74, 0x65,
0xEC, 0x6F, 0x75, 0x69, 0xEF, 0x63, 0x46, 0x53, 0xDA, 0x5D, 0x47,
0x57, 0xD1, 0x51, 0x4E, 0x5B, 0xD2, 0x55, 0x4F, 0x5F, 0xD9, 0x49, 0x56,
0x43, 0xCA, 0x4D, 0x57, 0x47, 0xC1, 0x41, 0x5E, 0x4B, 0xA9, 0x28, 0x30,
0x22, 0xA2, 0x2C, 0x31, 0x26, 0xA1, 0x20
]
value0 = [0x96, 0x19, 0x7, 0x11, 0x99, 0x19, 0x2, 0x11]
value2 = [
0x69, 0x22, 0x22, 0x38, 0x1F, 0x43, 0x5B, 0x1C, 0x45, 0xE, 0x3C,
0x8, 0x5, 0x5E, 0x30, 0x17, 0x5F, 0x1B, 0x6, 0x19, 0x3B, 0x44, 0x7, 0x17,
0x6E, 0x7, 0x53, 0x1E, 0x17, 0x55, 0x12
]
buf = ""
for i in range(0x3E):
buf += chr((value1[i] ^ value0[i % 8]) & 0xFF)
print(buf)
================================================================================
E:\JungJaeho\STUDY\Self\hacking\ctf\chrismasctf\c545e718-b031-4028-876c-1998a6ab071e>
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 // 연산된 값
C
복사
2.
사용자 입력값 8바이트와 1번을 통해 얻은 buf의 특정 인덱스 별 바이트 값을 비교하여 동일하게 세팅한다
...
my_input = ""
my_input += buf[0x35]
my_input += buf[0xE]
my_input += buf[0x2]
my_input += buf[0xA]
my_input += buf[0x3]
my_input += buf[0x34]
my_input += buf[0xE]
my_input += buf[0x11]
print(my_input)
================================================================================
E:\JungJaeho\STUDY\Self\hacking\ctf\chrismasctf\c545e718-b031-4028-876c-1998a6ab071e>
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 // 연산된 값
1ockd0or // 사용자가 입력해야하는 값!!
C
복사
3.
2번을 통해 얻은 사용자 입력값을 인자로 다시 특정 연산을 거친뒤 출력한다
...
result = ""
for i in range(0x1F):
result += chr((value2[i] ^ ord(my_input[i % len(my_input)])) & 0xFF)
print(result)
================================================================================
E:\JungJaeho\STUDY\Self\hacking\ctf\chrismasctf\c545e718-b031-4028-876c-1998a6ab071e>
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 // 연산된 값
1ockd0or // 사용자가 입력해야하는 값!!
XMAS{s4nta_can_enter_the_h0use}
C
복사
최종 페이로드는 다음과 같다
value1 = [
0xF7, 0x7B, 0x64, 0x75, 0xFC, 0x7F, 0x65, 0x79, 0xFF,
0x73, 0x6C, 0x7D, 0xF4, 0x77, 0x6D, 0x61, 0xE7, 0x6B, 0x74, 0x65,
0xEC, 0x6F, 0x75, 0x69, 0xEF, 0x63, 0x46, 0x53, 0xDA, 0x5D, 0x47,
0x57, 0xD1, 0x51, 0x4E, 0x5B, 0xD2, 0x55, 0x4F, 0x5F, 0xD9, 0x49, 0x56,
0x43, 0xCA, 0x4D, 0x57, 0x47, 0xC1, 0x41, 0x5E, 0x4B, 0xA9, 0x28, 0x30,
0x22, 0xA2, 0x2C, 0x31, 0x26, 0xA1, 0x20
]
value0 = [0x96, 0x19, 0x7, 0x11, 0x99, 0x19, 0x2, 0x11]
value2 = [
0x69, 0x22, 0x22, 0x38, 0x1F, 0x43, 0x5B, 0x1C, 0x45, 0xE, 0x3C,
0x8, 0x5, 0x5E, 0x30, 0x17, 0x5F, 0x1B, 0x6, 0x19, 0x3B, 0x44, 0x7, 0x17,
0x6E, 0x7, 0x53, 0x1E, 0x17, 0x55, 0x12
]
buf = ""
for i in range(0x3E):
buf += chr((value1[i] ^ value0[i % 8]) & 0xFF)
print(buf)
my_input = ""
my_input += buf[0x35]
my_input += buf[0xE]
my_input += buf[0x2]
my_input += buf[0xA]
my_input += buf[0x3]
my_input += buf[0x34]
my_input += buf[0xE]
my_input += buf[0x11]
print(my_input)
result = ""
for i in range(0x1F):
result += chr((value2[i] ^ ord(my_input[i % len(my_input)])) & 0xFF)
print(result)
Python
복사
4. 몰랐던 개념
•
arm 어셈 (aarch64)
•
str, ldr 순서. str은 ⇒, ldr은 <=
•
sxtw : signed 부호 확장 명령어
•
wzr : zero register로서 항상 0이 들어간다