使用基本汇编代码反转字节输入
Reversing byte input with basic assembly code
我正在参加一个 ctf,其中一个任务是使用类似程序集的环境反转一行输入字节。输入为 x 字节长,最后一个字节始终为 0x00。一个例子是:
输入4433221100,输出0011223344
我认为循环直到到达输入 00 的循环是一个开始的地方。
你们对如何解决这个问题有什么建议吗?我不需要特定的代码示例,但一些建议可以为我指明正确的方向。我只有基本的 alu 操作、跳转和条件跳转、存储和读取内存地址以及其他一些可用的基本内容。所有的alu操作都是mod256.
是的,通过搜索 0
字节来查找结束/长度来查找长度是一种开始方式。根据您想要的目的地位置,可以在搜索结束的同一循环中进行复制。
如果你想原地反转,你需要先找到结尾(有一个单独的循环)。然后您可以从两端加载,将寄存器存储到相反的位置,并向内移动您的指针,直到它们交叉,标准就地反转,您可以在任何地方找到示例。
如果你想反向复制到其他space,你可以一次通过源 (没有先找到长度)。从缓冲区的末尾开始存储输出,随着读取指针的增加而减少输出指针。完成后,您将获得一个指向反向副本起点的指针,您可以将其传递给输出函数。你不会知道你要停在哪里,所以缓冲区需要足够大。但是由于您只是将指针传递给另一个函数,所以您不知道(直到完成复制)反向副本的开始位置。
你仍然可以单独找到长度然后复制,但那样效率很低。
如果您需要反向副本从另一个缓冲区中的某个已知位置开始(例如附加到另一个字符串或数组),您会 在存储任何内容之前需要长度或指向末尾的指针,因此这是一个 2 遍操作,就像就地反转一样。
然后您可以向后读取源并向前写入目标(或一次“输出”每个字节 1 到某个 IO 流)。您的循环终止条件可以是递减计数器或使用寄存器中的指针进行指针比较,将 src 与已知的源开始或 dst 与目标的计算结束进行比较。
或者您可以向前阅读源文件,直到到达您找到的结尾位置,从计算出的目的地应该到达的位置开始以相反的顺序存储。
(如果你的机器像 6502 并且可以很容易地索引到一个静态数组,但不容易将整个指针保存在一个寄存器中,显然你会想要使用从 0 开始计数的索引。这使得检测开始更简单,如 sub reg, 1 / jnz if subtract 已经为要测试的条件分支设置了标志。)
save your stackpointer in a variable
for each byte of the string
push byte onto the stack
repeat if byte was <> 0
pull byte from stack
output byte
repeat until old_stackpointer is reached
在 6502 汇编器中,这看起来像
tsx
stx OLD_STACKPTR
ldy#$ff
loop:
iny
lda INPUT,y
pha
bne loop
ldy#$ff
loop2:
iny
pla
sta INPUT,y
tsx
cpx OLD_STACKPTR
bne loop2
我正在参加一个 ctf,其中一个任务是使用类似程序集的环境反转一行输入字节。输入为 x 字节长,最后一个字节始终为 0x00。一个例子是:
输入4433221100,输出0011223344
我认为循环直到到达输入 00 的循环是一个开始的地方。
你们对如何解决这个问题有什么建议吗?我不需要特定的代码示例,但一些建议可以为我指明正确的方向。我只有基本的 alu 操作、跳转和条件跳转、存储和读取内存地址以及其他一些可用的基本内容。所有的alu操作都是mod256.
是的,通过搜索 0
字节来查找结束/长度来查找长度是一种开始方式。根据您想要的目的地位置,可以在搜索结束的同一循环中进行复制。
如果你想原地反转,你需要先找到结尾(有一个单独的循环)。然后您可以从两端加载,将寄存器存储到相反的位置,并向内移动您的指针,直到它们交叉,标准就地反转,您可以在任何地方找到示例。
如果你想反向复制到其他space,你可以一次通过源 (没有先找到长度)。从缓冲区的末尾开始存储输出,随着读取指针的增加而减少输出指针。完成后,您将获得一个指向反向副本起点的指针,您可以将其传递给输出函数。你不会知道你要停在哪里,所以缓冲区需要足够大。但是由于您只是将指针传递给另一个函数,所以您不知道(直到完成复制)反向副本的开始位置。
你仍然可以单独找到长度然后复制,但那样效率很低。
如果您需要反向副本从另一个缓冲区中的某个已知位置开始(例如附加到另一个字符串或数组),您会 在存储任何内容之前需要长度或指向末尾的指针,因此这是一个 2 遍操作,就像就地反转一样。
然后您可以向后读取源并向前写入目标(或一次“输出”每个字节 1 到某个 IO 流)。您的循环终止条件可以是递减计数器或使用寄存器中的指针进行指针比较,将 src 与已知的源开始或 dst 与目标的计算结束进行比较。
或者您可以向前阅读源文件,直到到达您找到的结尾位置,从计算出的目的地应该到达的位置开始以相反的顺序存储。
(如果你的机器像 6502 并且可以很容易地索引到一个静态数组,但不容易将整个指针保存在一个寄存器中,显然你会想要使用从 0 开始计数的索引。这使得检测开始更简单,如 sub reg, 1 / jnz if subtract 已经为要测试的条件分支设置了标志。)
save your stackpointer in a variable
for each byte of the string
push byte onto the stack
repeat if byte was <> 0
pull byte from stack
output byte
repeat until old_stackpointer is reached
在 6502 汇编器中,这看起来像
tsx
stx OLD_STACKPTR
ldy#$ff
loop:
iny
lda INPUT,y
pha
bne loop
ldy#$ff
loop2:
iny
pla
sta INPUT,y
tsx
cpx OLD_STACKPTR
bne loop2