duangsuse::Echo
718 subscribers
4.26K photos
130 videos
583 files
6.48K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
https://wiki.alpinelinux.org/wiki/Installing_Alpine_Linux_in_a_chroot #Sysadmin 正在准备新的 Alpine #Linux X86 Chroot 容器....

LD_LIBRARY_PATH=`pwd`/alpine-minirootfs-3.8.1-x86/usr/lib:`pwd`/alpine-minirootfs-3.8.1-x86/lib /lib/ld-linux.so.2 ./alpine-minirootfs-3.8.1-x86/usr/bin/lua5.1

我居然用上了容器里的 Lua5.1...
duangsuse::Echo
Photo
...因为的确已经熬了一夜了,而且这些的确是首先以学习为主...
(主要还是想让程序能运行起来... 成天和 linker、relocatable、shared object、静态链接动态链接杠... 我真的不想熬夜啊...
我决定再重新逆向 BEL 函数,成功了就睡觉...唉
This media is not supported in your browser
VIEW IN TELEGRAM
duangsuse::Echo
...因为的确已经熬了一夜了,而且这些的确是首先以学习为主... (主要还是想让程序能运行起来... 成天和 linker、relocatable、shared object、静态链接动态链接杠... 我真的不想熬夜啊... 我决定再重新逆向 BEL 函数,成功了就睡觉...唉
function BEL() {
push ebp; ebp = esp

eax = dword [ebp + 0x8]
ecx = [eax + 2]

edx = 0x55555556
eax = ecx

eax = edx = eax * edx ; imul edx

eax = ecx

eax >>= 0x1f ; sar eax, 0x1f
edx -= eax
eax = edx
eax <<<= 2 ; shl eax, 2
eax += 1 ; add eax, 1
}
foo.tar
10 KB
非常失败,我根本不知道为什么要先 mov eax, [ebp + 8]mov ecx, [eax + 2],这种看起来根本对不齐一个字的操作到底有什么意义...
#sysadmin #Assembly #reveng #failure #life

算是体验了一下 NASM 和 x86_64 交叉 x86,此外,没有别的。
弄出等价的后可以看看是如何优化的
duangsuse::Echo
function BEL() { push ebp; ebp = esp eax = dword [ebp + 0x8] ecx = [eax + 2] edx = 0x55555556 eax = ecx eax = edx = eax * edx ; imul edx eax = ecx eax >>= 0x1f ; sar eax, 0x1f edx -= eax eax = edx eax <<<= 2 ; shl eax, 2 eax…
int BEL(int n) { return (4 * (n - 1) / 3 | 3) + 2; }

使用逆波兰法表示

bel
(n) = ((n-1) * 4 / 3) | 3 + 3

ldarg.0
ldint 1
dec ; n - 1
ldint 4
mul ; (n - 1) * 4
ldint 3
div ; (n - 1) * 4 / 3
ldint 3
or.bitwise ; |3
ldint 3
add ; + 3

function BEL (edi: int n) {
push rbp; rbp = rsp

dword [local_i32] = edi
eax = dword [local_4h]
eax -= 1 ; (n - 1)
ecx = [rax*4] (n - 1) * 4

; / 3 + 1
edx = 0x55555556
eax = ecx
eax = eax * edx
eax = ecx
eax >>= 0x1f
edx -= eax
eax = edx

; | 3
eax |= 3

; + 2
eax += 2

return 2
}
duangsuse::Echo
int BEL(int n) { return (4 * (n - 1) / 3 | 3) + 2; } 使用逆波兰法表示 bel(n) = ((n-1) * 4 / 3) | 3 + 3 ldarg.0 ldint 1 dec ; n - 1 ldint 4 mul ; (n - 1) * 4 ldint 3 div ; (n - 1) * 4 / 3 ldint 3 or.bitwise ; |3 ldint 3 add ; + 3 function BEL (edi: int n) { push…
#Ruby 中也可以模拟

因为这次实在是太失败了,但我对这种极端干扰生活的情况很绝望,,, 因为足足一晚上没合眼,而且早上也没吃饭
希望以后能做到吧,虽然都还不熟悉呢... 太菜了啊... 现在居然连最基本的都弄不懂... 看不到运行时 esp、ebp 到底做了什么
当然位运算就更不可能看到本质了... 就不能逆向而理解呢

class Stack
def initialize(stack = [])
@fifo = stack
end
def ld(o); @fifo << o; end
def pop; @fifo.pop; end
def peek; @fifo.last; end
def size; @fifo.size; end
def to_s; @fifo.to_s; end
def eql?(o); @fifo.eql?(o); end
def <<(o); ld o; end
end

def Stack.mk_binary_op(name, &operator)
define_method(name) do
op2 = pop; op1 = pop
ld operator.call(op1, op2)
end
end

class Stack
mk_binary_op :sub, &:-
mk_binary_op :add, &:+
mk_binary_op :mul, &:*
mk_binary_op :div, &:/
mk_binary_op :bitwise_or, &:|
end


然后看主程序

def stack_bel(n)
s = Stack.new
s << 4 << n << 1
s.sub
s.mul
s << 3
s.div
s << 3
s.bitwise_or
s << 2
s.add
return s.pop
end

1000.times { |i| print stack_bel(i); print ' ' }
Forwarded from dnaugsuz
如果说开始 mov eax, [ebp - 8] 这种可以理解为分配 retAddress(当然其实不是,我误会了),那后来... 我中间有段时间在想是不是在传指针解引用,但传入的参数分明不是指针...

mov ecx, [eax - 2] 这种又是什么鬼啊,这不是 x86 么,32 位啊,根本不应该出现这种一个栈帧占 10 字节的情况么... 它不是 2 的幂啊...

x86 里怎么会莫名其妙栈上分配一个字又一个半字的数据呢...
... 而 [eax - 4] 这种我还可以理解,这种毫无逻辑的分配是什么意思啊...

我拿 NASM 重写了代码然后上 edb 逐 step 调试,结果好像证明它的确需要一个指针(ebp - 8 是第一个数值参数,然后它解指针这个参数),可是我当时测试的时候给的真的不是指针啊... 是直接传值调用的啊...
RetDec 反编译的全是错的,它根本没有注意到这个函数不是无参的,还不如 radare2 提示的类型正确... 看来还是上动态分析可选
#reveng 所以现在 duangsuse 睡了一觉后重整旗鼓,端正自己的态度,一切为了学习底层知识而不是专门彻底逆向工程还原出一个等价的 liba.so

现在 duangsuse 思考了一下,又重新理解了 x86 上 C 语言的各种小 routines 了,知道 stack base 和 stack pointer 怎么管理了,想清楚静态链接、动态链接、可重定位文件、共享库有什么区别可以怎么 hack 了,又会写汇编了,现在写一个 1 + 1 的 NASM x86 32b helloworld 程序看看:

#Learn NASM #backend #code

section .rodata
fmt db `%s %i\n`, 0x0

section .data
msg db "Hello, world!", 0x0

section .text

extern printf

global _start
global main
global print

_start:
mov ebp, esp

; arguments to main:
; _start(int argc, char **argv)
call main

; exit(eax)
mov ebx, eax
mov eax, 1
int 0x80

print:
push ebp
mov ebp, esp

mov ecx, 100
add ecx, 1
push ecx
push msg
push fmt
call printf

; clean-up for `printf' call
; increase stack pointer by argument size
; to simply ignore them
; sizeof(int) + sizeof(char *) * 2
add esp, 12

leave
ret

main:
push ebp
mov ebp, esp

call print

xor eax, eax
leave
ret

nasm -felf 1p1helo.asm; ld -m elf_i386 1p1helo.o -lc -o helloworld -I /usr/lib/ld-2*;./helloworld

duangsuse 准备用刚编译的 32 位 Lua 和 GNU Binutils 重新调整测试一下新的 liba.so,解决 ABI 不同 ld 解释器动态链接受到阻碍的问题,并且搞懂 BEL 里的莫名其妙的指令序列到底做什么的,可能会上动态分析

首先准备了解下为什么每次 x86 Alpine 容器里动态链接好了都会 Segfault,对比一下自己实现的 BEL 和酷安原本的有什么区别。
了解 BEL 如何执行

然后就是随便再选一个符号还原代码
终于弄懂了...
Forwarded from dnaugsuz
我注意了一下上一个 ebp 和 esp 的变化,的确是以 2 为单位的... 从 ...250 到 ..518 了,16 位一个内存地址,貌似上一次 _start 里 mov ebp, esp 后 esp 又 push 了 call main 调用的 retAddr(32b) 上去,然后又 push 了个 ebp(32b),大概是以 32 位为单位的
This media is not supported in your browser
VIEW IN TELEGRAM
x86_nasm_helloworld.tar
20 KB
#code #backend #dev #asm 整理了一下构建工具什么的
duangsuse::Echo
x86_nasm_helloworld.tar
比较友好,虽然没有用到流程控制分支和循环什么的

也没有 bss 静态未初始化变量

不过倒是有函数调用,非常简洁,看不懂 GNU AS 应该也能看懂
#reveng duangsuse 终于重拾自信,好耶!是 x86 intel syntax 汇编!
  mov ebx, 100
mov edi, 0

loop:

push edi
call BEL
call printN

inc edi
cmp edi, ebx
jnz loop

call printLn

xor eax, eax
leave
ret
#code